创建型模式:原型模式

个人公众号原文:
创建型模式:原型模式

景

五大创建型模式之五:原型模式。

简介

姓名 :原型模式

英文名 :Prototype Pattern

价值观 :效率第一

个人介绍

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
(来自《设计模式之禅》)

又到了一个系列的最后一篇文章了,今天是创建型模式的最后一篇。什么是创建型模式呢?创建型模式是对类的实例化过程进行抽象,使对象的创建和使用分离,从而使代码更加灵活。

我们平时使用最多的一种创建对象方式就是 new ABC(),直接通过构造方法来创建一个对象。通过原型模式来创建对象则不用调用构造方法,就可以创建一个对象。下面来揭开它的面纱。

你要的故事

前几天有出版社的老师邀请写书,鉴于深知自己水平还不足以出书,所以没有合作,还在努力学习,以后有能力有机会再考虑这方面的事情。

今天的故事就从出书讲起。我们知道一本新书发版的时候,会复印很多册,如果销售得好,会有很多个印刷版本。我们来了解复印一批书籍这个过程是怎么实现的。小明写下了下面这段代码。

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
public class NoPrototypeTest {

public static void main(String[] args) {
for (int i = 1; i <= 10; i ++) {
Book book = new Book("娱乐至死", "尼尔波兹曼", "社会科学", "XXXX");
System.out.println("复印书籍:" + book.getName() + ",第 " + i + " 本");
}
}

}

class Book {
private String name;
private String author;
private String type;
private String content;

public Book(String name, String author, String type, String content) {
this.name = name;
this.author = author;
this.type = type;
this.content = content;
System.out.println("实例化书籍:" + this.name);
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

// 打印结果:
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 1
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 2
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 3
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 4
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 5
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 6
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 7
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 8
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 9
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 10

上面小明的代码复印了 10 本《娱乐至死》,代码逻辑没有问题,有个问题就是复印一本就实例化一次书籍,这个实例化可以减少么?使用原型模式可以实现。小明根据这些提示,重新修改了代码。

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
public class PrototypeTest {

public static void main(String[] args) {
Book2 book1 = new ConcreteBook("娱乐至死", "尼尔波兹曼", "社会科学", "XXXX");
System.out.println("复印书籍:" + book1.getName() + ",第 " + 1 + " 本");
for (int i = 2; i <= 10; i ++) {
Book2 book2 = (Book2) book1.clone();
System.out.println("复印书籍:" + book2.getName() + ",第 " + i + " 本");
}


}

}

/**
* 抽象类
*/
abstract class Book2 implements Cloneable {

private String name;
private String author;
private String type;
private String content;

public Book2(String name, String author, String type, String content) {
this.name = name;
this.author = author;
this.type = type;
this.content = content;
System.out.println("实例化书籍:" + this.name);
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}

/**
* 具体类
*/
class ConcreteBook extends Book2 {

public ConcreteBook(String name, String author, String type, String content) {
super(name, author, type, content);
}
}

打印结果:
实例化书籍:娱乐至死
复印书籍:娱乐至死,第 1
复印书籍:娱乐至死,第 2
复印书籍:娱乐至死,第 3
复印书籍:娱乐至死,第 4
复印书籍:娱乐至死,第 5
复印书籍:娱乐至死,第 6
复印书籍:娱乐至死,第 7
复印书籍:娱乐至死,第 8
复印书籍:娱乐至死,第 9
复印书籍:娱乐至死,第 10

看,打印结果和第一次实现的结果完全不一样,这一次只实例化了一次,后面复印的书籍都没有实例化。我们看看代码的变化,代码中最最主要的就是 Book2 实现了 Cloneable 接口,这个接口有个 clone() 方法,通过实现这个方法,可以实现对象的拷贝,就是不用调用构造方法,直接通过对内存的拷贝来创建一个新的对象。这就是原型模式的实现方式,通过原型模式可以提高创建对象的效率

代码:
Prototype Pattern

总结

通过原型模式,绕过构造方法创建对象,利用内存直接拷贝对象,提高对象的创建性效率。在有大量的对象创建或者类初始化消耗多资源的场景下可以利用原型模式来优化。当然在实现的过程中,要注意浅拷贝与深拷贝的问题,防止写出 bug,文章主要介绍原型模式,就不详细说这个问题了,留给大家去扩展了解。

参考资料:《大话设计模式》、《Java设计模式》、《设计模式之禅》、《研磨设计模式》、《Head First 设计模式》

推荐阅读:
创建型模式:单例模式
创建型模式:工厂方法
创建型模式:抽象工厂
创建型模式:原型模式
公众号之设计模式系列文章

希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号:LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。



公众号