设计模式之创建型模式总结 - Creational Patterns

前言

以前学习设计模式的时候, 通常都是咖啡馆, 披萨店, 各种各样的红绿头鸭. 明显地, 这些概念需要更新一下, 这次我们用MacBook和XPS13两台电脑作为例子来快速复习创建型设计模式.

创建型模型简单直接, 所以大部分模式直接通过UML进行展示, 个别需要特别注意的将会以代码的形式展示.

完整代码已上传至GitOSC

简单工厂

简单工厂可以为客户端选择具体的实现

下面是LaptopFactory生产MacBook和Xps13的例子

UML

简单工厂模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        // 生成rmbp
        final MacBook implA = LaptopFactory.createMacBook();
        implA.doSomething();
        // 生产xps
        final Xps13 implB = LaptopFactory.createXps13();
        implB.doSomething();
    }
}

工厂方法模式 - Factory method

与简单工厂的区别在于工厂方法模式允许将类的实例化推迟到子类中, 如果把工厂方法中的具体实现放到父类中, 那么就等同于简单工厂

下面是LaptopFactory将生产Laptop的功能分别推迟至AppleFactoryDellFactory的例子

UML

工厂方法模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final LaptopFactory laptopFactory = new AppleFactory();
        laptopFactory.someWork();
    }
}

小结

工厂父类是一个抽象类, 里面有个protected abstract方法就是工厂方法

一般工厂方法返回的是被创建对象的接口对象, 当然也可以是抽象类或者一个具体的类的实例

工厂方法可以看成一个生成对象的抽象方法

抽象工厂模式 - Abstract factory

创建一系列的产品对象, 而且这一系列对象是构建新的对象所需要的组成部分, 简而言之就是这一系列被创建的对象相互之间是有约束的.

如今不仅需要生产电脑, 还要生产电源适配器, 这两个组成了产品簇. 显而易见的是XPS不能使用MacBook的电源.

UML

抽象工厂模式

Client Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final LaptopFactory factory = new AppleFactory();
        factory.createLaptop();
        factory.createPowerAdaptor();
    }
}

原型模式 - Prototype

<u>可忽略</u>, 在实际工作中更多地会使用第三方类库完成深拷贝

下面是克隆MacBook的例子

UML

原型模式

Usage

/**
 * @author Zhao Junjian
 */
public class PrototypeTester {
    @Test
    public void testClone() throws Exception {
        // 你就只管我们生成一个List对象就行
        final List<MacBook.Cpu> cpuList = new ArrayList<>();
        for (int i = 1; i <= 4; i++) {
            final MacBook.Cpu cpu = new MacBook.Cpu(i);
            cpuList.add(cpu);
        }
        final MacBook macBook = new MacBook();
        macBook.setCpuArray(cpuList.toArray(new MacBook.Cpu[cpuList.size()]));
        macBook.setCpuList(cpuList);
        macBook.setKeyboard(87);
        macBook.setMemory("16G");
        // 全部准备完成, 我们就开始克隆一个新的实体
        final MacBook newMacBook = macBook.clone();
        Assert.assertEquals(macBook, newMacBook);
        // 修改引用类型
        final MacBook.Cpu newCpu = new MacBook.Cpu(5);
        cpuList.add(newCpu);
        newMacBook.setCpuList(cpuList);
        // 如果这里抛出异常, 就证明是浅拷贝. 实际情况就是浅拷贝.
        Assert.assertNotEquals(macBook, newMacBook);
    }
}

小结

MacBook需要实现标识接口Cloneable, 并在clone()方法里面显式地调用父类的clone()

@Override
protected MacBook clone() throws CloneNotSupportedException {
  return (MacBook) super.clone();
}

单例模式 - Singleton

这里着重于讲解懒汉式, 因为有需要注意的细节, 所以直接贴代码.

实现单例有3种模式, 嵌套类, 双重检查和枚举

嵌套类 holder
/**
 * @author Zhao Junjian
 */
public class DellFactory {

    private DellFactory() {
        System.out.println("dell is the best");
    }

    private static final class DellFactoryHolder {
        private static final DellFactory FACTORY = new DellFactory();
    }

    public static DellFactory getInstance() {
        return DellFactoryHolder.FACTORY;
    }

}
双重检查 double-checked
/**
 * @author Zhao Junjian
 */
public class AppleFactory {
    private static volatile AppleFactory FACTORY;

    public static AppleFactory getInstance() {
        if (FACTORY == null) {
            //Client.LATCH.await();
            synchronized (AppleFactory.class) {
                if (FACTORY == null) {
                    FACTORY = new AppleFactory();
                }
            }
        }
        return FACTORY;
    }

    private AppleFactory() {
        System.out.println(Thread.currentThread().getName() + " wanna get a hurt");
    }

}
枚举 enum
/**
 * @author Zhao Junjian
 */
public enum RazerFactory {
    STEALTH;

    public void doSomething() {
        // ...
    }
}

建造者模式/生成器模式 - Builder

实际中有两种方法可以快速构建Fluent API, 第一是安装插件, 第二是使用Lombok

被构建者的私有构造器, 公开静态的builder()方法

下面是通过建造者生成MacBook的例子

/**
 * @author Zhao Junjian
 */
@Data
public class MacBook {
    private String processor;

    private int memory;

    private long capacity;

    private String keyboard;

    private MacBook(Builder builder) {
        processor = builder.processor;
        memory = builder.memory;
        capacity = builder.capacity;
        keyboard = builder.keyboard;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static final class Builder {
        private String processor;
        private int memory;
        private long capacity;
        private String keyboard;

        public Builder processor(String val) {
            processor = val;
            return this;
        }

        public Builder memory(int val) {
            memory = val;
            return this;
        }

        public Builder capacity(long val) {
            capacity = val;
            return this;
        }

        public Builder keyboard(String val) {
            keyboard = val;
            return this;
        }

        public MacBook build() {
            return new MacBook(this);
        }
    }
}

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final MacBook macBook = MacBook.builder().processor("core").memory(9481).capacity(102931L).build();
    }
}

作者:Chris
原博客:http://blog.chriscs.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,738评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,377评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,774评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,032评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,015评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,239评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,724评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,374评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,410评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,457评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,132评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,733评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,804评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,022评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,515评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,116评论 2 341

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 选择组装电脑的配件## 举个生活中常见的例子——组装电脑,我们在组装电脑的时候,通常需要选...
    七寸知架构阅读 4,245评论 6 66
  • 1 场景问题# 1.1 导出数据的应用框架## 考虑这样一个实际应用:实现一个导出数据的应用框架,来让客户选择数据...
    七寸知架构阅读 6,447评论 6 72
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,885评论 1 15
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,537评论 18 399
  • 所谓奔波 大概就是外衣上沾满风尘 内衣里吸满汗水 看遍万种光景 依然不能平静
    cookie猫阅读 531评论 0 0