logo头像
ICQL

designpattern_创建型

创建型设计模式概述

主要解决对象的创建问题



单例模式

定义:一个类只允许创建一个实例
使用场景:处理资源访问冲突;数据在系统种只应该保存一份(如配置信息)
实现方式:主要考虑以下3个方面:构造函数private,创建对象线程安全,是否延迟加载

存在的问题:

单例对OOP特性支持不友好:封装/继承/多态/抽象
单例会隐藏类之间的依赖关系:类似于工具类一样使用时属于硬编码,不便查找
单例对代码的扩展性不友好
单例对代码的可测试性不友好:由于类似硬编码,不方便mock
单例不支持有参数的构造函数

单例的替代方式:工厂模式,ioc容器

单例的作用范围:

进程内唯一(大多数情况)
线程内唯一(用类似ThreadLocal的Map即可实现)
多进程内唯一(分布式),用一个集中式的共享区域存储,如db数据库等

1)饥饿式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 单例:饥饿模式——类加载时就创建对象
* 过早占用内存,存在性能问题?
* 若初始化耗时,应该在应用启动时就初始化好,避免使用时再创建出现性能问题
* 占用内存多?按照fail-fast设计原则(有问题及早暴漏),启动时就能检查内存是否够用
*/
public final class EagerSingleton {
/**
* 类加载的时候执行clinit()时将创建对象,线程安全
*/
private static final EagerSingleton INSTANCE = new EagerSingleton();

private EagerSingleton() {
}

public static EagerSingleton getInstance() {
return INSTANCE;
}
}

2)懒汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 单例:懒汉模式——延迟加载
* 同步范围过大(锁对象为类Class对象),性能不佳
*/
public final class LazySingleton {

private static LazySingleton INSTANCE;

private LazySingleton() {
}

public synchronized static LazySingleton getInstance() {
if (INSTANCE != null) {
INSTANCE = new LazySingleton();
}
return INSTANCE;
}
}

3)双重检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 单例:双重检测
*
* 初始化对象的3个步骤:
* 1)分配内存空间
* 2)初始化对象
* 3)将内存空间的地址赋值给对应的引用
* 由于虚拟机有指令重排优化机制,上述步骤可能会变为 1-3-2,所以需要 volatile 关键字来保证禁止重排指令,
* 如果以1-3-2顺序执行,线程A运行到第2次检查通过后正在初始化对象,初始化对象需要一定时间,这时步骤已完成1和3,
* 线程B运行到第1次检查发现不为null,则直接返回,实际上 线程A还没有完成初始化对象的步骤2,造成了jvm异常
*/
public final class DoubleCheckedSingleton {

private volatile static DoubleCheckedSingleton INSTANCE;

private DoubleCheckedSingleton() {
}

public static DoubleCheckedSingleton getInstance() {
//第1次检查
if (INSTANCE == null) {
synchronized (DoubleCheckedSingleton.class) {
//第2次检查
if (INSTANCE == null) {
INSTANCE = new DoubleCheckedSingleton();
}
}
}
return INSTANCE;
}
}

4)静态内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 单例:内部类-懒加载
*/
public final class InnerClassSingleton {
private InnerClassSingleton() {
}

private static class SingletonHolder {
public static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}

public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

5)枚举

1
2
3
4
5
6
/**
* 单例:枚举
*/
public enum EnumSingleton {
INSTANCE
}


多例模式

特殊的单例,一个类允许有固定的多个实例,区别于工厂模式,多例是同一个类型的多个实例,而工厂模式是多个不同子类的实例

实现方式:枚举 或 使用map结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 多例:枚举
*/
public enum EnumMultiton {
INSTANCE1,
INSTANCE2,
INSTANCE3
}

/**
* 多例:双重检测
*/
public final class DoubleCheckedMultiton {

private static final Map<String, DoubleCheckedMultiton> INSTANCE_BY_NAME = new HashMap<>();

private DoubleCheckedMultiton() {
}

public static DoubleCheckedMultiton getInstance(String name) {
DoubleCheckedMultiton INSTANCE = INSTANCE_BY_NAME.get(name);
//第1次检查
if (INSTANCE == null) {
synchronized (DoubleCheckedMultiton.class) {
//第2次检查
if (INSTANCE == null) {
INSTANCE = new DoubleCheckedMultiton();
INSTANCE_BY_NAME.put(name, INSTANCE);
}
}
}
return INSTANCE;
}
}


工厂模式

用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象

1)简单工厂

工厂类直接创建对象,static方法,最简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* 简单工厂模式
*/
public class Factory {

private static final Map<String, IObject> OBJECT_BY_TYPE = new HashMap<>();

static {
OBJECT_BY_TYPE.put("A", new ObjectA());
OBJECT_BY_TYPE.put("B", new ObjectB());
OBJECT_BY_TYPE.put("C", new ObjectC());
}

public static IObject createObject(String type) {
if (type == null || type.isEmpty()) {
return null;
}
return OBJECT_BY_TYPE.get(type.toUpperCase());
}
}

public interface IObject {
}

public class ObjectA implements IObject {
}

public class ObjectB implements IObject {
}

public class ObjectC implements IObject {
}

2)工厂方法

将创建对象的行为下沉到各个类型自己的工厂类中,这些类型工厂类实现一个工厂接口,和工厂接口一起再使用一个简单工厂模式对外暴漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* 工厂方法模式
*/
public class Factory {

private static final Map<String, ObjectFactory> FACTORY_BY_TYPE = new HashMap<>();

static {
FACTORY_BY_TYPE.put("A", new ObjectAFactory());
FACTORY_BY_TYPE.put("B", new ObjectBFactory());
FACTORY_BY_TYPE.put("C", new ObjectCFactory());
}

public static ObjectFactory createObject(String type) {
if (type == null || type.isEmpty()) {
return null;
}
return FACTORY_BY_TYPE.get(type.toUpperCase());
}
}

public interface IObject {
}

public interface ObjectFactory {
IObject createObject(String type);
}

public class ObjectAFactory implements ObjectFactory {
@Override
public IObject createObject(String type) {
//复杂的创建逻辑
return new ObjectA();
}
}

public class ObjectBFactory implements ObjectFactory {
@Override
public IObject createObject(String type) {
//复杂的创建逻辑
return new ObjectB();
}
}

public class ObjectCFactory implements ObjectFactory {
@Override
public IObject createObject(String type) {
//复杂的创建逻辑
return new ObjectC();
}
}

public class ObjectA implements IObject {
}

public class ObjectB implements IObject {
}

public class ObjectC implements IObject {
}

3)抽象工厂

不常用,相当于原来的实例可以通过两个维度去划分,在工厂方法的基础上,每个维度创建实例都在工厂方法中有对应的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* 抽象工厂模式
*/
public class Factory {

private static final Map<String, ObjectFactory> FACTORY_BY_TYPE = new HashMap<>();

static {
FACTORY_BY_TYPE.put("A", new ObjectAFactory());
FACTORY_BY_TYPE.put("B", new ObjectBFactory());
FACTORY_BY_TYPE.put("C", new ObjectCFactory());
}

public static ObjectFactory createObject(String type) {
if (type == null || type.isEmpty()) {
return null;
}
return FACTORY_BY_TYPE.get(type.toUpperCase());
}
}

public interface IObject {
}

public interface IObjectA extends IObject {
}

public interface IObjectB extends IObject {
}

public interface IObjectC extends IObject {
}

public interface ObjectFactory {

IObject createObject1(String type);

IObject createObject2(String type);
}

public class ObjectA1 implements IObjectA {
}

public class ObjectA2 implements IObjectA {
}

public class ObjectB1 implements IObjectB {
}

public class ObjectB2 implements IObjectB {
}

public class ObjectC1 implements IObjectC {
}

public class ObjectC2 implements IObjectC {
}

public class ObjectAFactory implements ObjectFactory {
@Override
public IObject createObject1(String type) {
//复杂的创建逻辑
return new ObjectA1();
}

@Override
public IObject createObject2(String type) {
return new ObjectA2();
}
}

public class ObjectBFactory implements ObjectFactory {

@Override
public IObject createObject1(String type) {
//复杂的创建逻辑
return new ObjectB1();
}

@Override
public IObject createObject2(String type) {
//复杂的创建逻辑
return new ObjectB2();
}
}

public class ObjectCFactory implements ObjectFactory {

@Override
public IObject createObject1(String type) {
//复杂的创建逻辑
return new ObjectC1();
}

@Override
public IObject createObject2(String type) {
//复杂的创建逻辑
return new ObjectC2();
}
}


建造者模式

用来创建一种类型的复杂对象,通过设置不同的可选参数,”定制化”地创建不同的对象
对象一旦创建就不允许修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 建造者模式
*/
public class ObjectPool {

private int fieldA;

private String fieldB;

private ObjectPool(Builder builder) {
this.fieldA = builder.fieldA;
this.fieldB = builder.fieldB;
}

public static class Builder {

private int fieldA;

private String fieldB;

public ObjectPool build() {
//创建ObjectPool逻辑处理
if (fieldA < 0) {
throw new IllegalArgumentException("...");
}
if (fieldB == null || fieldB.isEmpty()) {
throw new IllegalArgumentException("...");
}
return new ObjectPool(this);
}

public Builder setFieldA(int fieldA) {
if (fieldA < 0) {
throw new IllegalArgumentException("...");
}
this.fieldA = fieldA;
return this;
}

public Builder setFieldB(String fieldB) {
if (fieldB == null || fieldB.isEmpty()) {
throw new IllegalArgumentException("...");
}
this.fieldB = fieldB;
return this;
}
}
}


原型模式

对象的创建成本较大,直接根据已有对象复制一个新的对象的方式
深拷贝(Deep Copy)和浅拷贝(Shallow Copy)

1
2
3
4
5
6
7
8
9
/**
* 原型模式
*/
public class ProtoType {
/**
* 深拷贝,浅拷贝
* 原型模式使用深拷贝,一般使用序列化相对简单,jdk原生序列化,json序列化,kryo序列化。。。
*/
}
微信打赏

赞赏是不耍流氓的鼓励