# 什么是原型设计模式
> 这里与软件工程中的原型开发模式有那么一点类似的地方,我们首先需要构建出一个原型,这个原型可以在现实开发中抽象出来的具体类型,但是这个类型与具体的类又不同,需要抽取公共的部分,通过构建管理器,实现创建不同需要的类型,
### 考虑使用原型设计模式的三种情况
第一种情况是需要处理的对象太多,如果将它们分别作为一个类,必须要编写很多个类文件难以根据类生成实例时
第二种情况是生成实例的过程太过复杂,很难根据类来生成实例。例如,我们假设这里有一个实例,即表示用户在图形编辑器中使用鼠标制作出的图形的实例。想在程序中创建这样的实例是常困难的,通常,在想生成一个和之前用户通过操作所创建出的实例完全一样的实例的时候,我们会事先将用户通过操作所创建出的实例保存起来,然后在需要时通过复制来生成新的实例想解藕框架与生成的实例时
第三种情况是想要让生成实例的框架不依赖于具体的类。这时,不能指定类名来生成实例,而要事先“注册”一个“原型”实例,然后通过复制该实例来生成新的实例。
### 类接口表关系表
包 | 类名 | 描述 |
framework | manager | 调用createclone |
framework | product | use createclone |
naN | rectangle | 具体打印矩形 |
nan | triangle | 具体打印三角形 |
是由product担任的
实现赋值新实例的方法 由具体的你需要的角色来担任
通过调用createclone 创建新的实例,由Manger类扮演这个角色
### uml
在接口中是交给子类去实现的
创建具体的对象
- code framework
1 package base.prototype.framework;
2
3
4
5 /**
6
7 * @program: DesignPatterns
8
9 * @description: 声明use, createclone具体复用
10
11 * @author: Mr.Dai
12
13 * @create: 2018-05-28 21:28
14
15 **/
16
17 public interface Product extends Cloneable {
18
19
20
21 public abstract void use(int len);
22
23 public abstract Product createClone();
24
25
1 import java.util.HashMap;
2
3
4
5 /**
6
7 * @program: DesignPatterns
8
9 * @description: 产生具体的类,维护多重对象
10
11 * @author: Mr.Dai
12
13 * @create: 2018-05-28 21:31
14
15 **/
16
17 public class Manager {
18
19 private HashMap<String,Product> warehouse=new HashMap<>();
20
21
22
23 public void registers(String name,Product product){
24
25 warehouse.put(name,product);
26
27 }
28
29
30
31 public Product createObj(String name){
32
33 Product product = warehouse.get(name);
34
35 return product.createClone();
36
37 }
38
39
- code domain 具体的实现的类
1 /**
2
3 * @program: DesignPatterns
4
5 * @description: 打印矩形
6
7 * @author: Mr.Dai
8
9 * @create: 2018-05-28 21:38
10
11 **/
12
13 public class Rectangle implements Product {
14
15
16
17 private char mark = '*';
18
19
20
21 public Rectangle(char mark) {
22
23 this.mark = mark;
24
25 }
26
27
28
29 public Rectangle() {
30
31 }
32
33
34
35 @Override
36
37 public void use(int len) {
38
39 for (int i = 0; i < len; i++) {
40
41 if(i==0||i==len-1){
42
43 for (int k = 0; k < len; k++) System.out.print(mark);
44
45 }else{
46
47 System.out.print('*');
48
49 for (int j = 0; j < len-2; j++) {
50
51 System.out.print(' ');
52
53 }
54
55 System.out.print('*');
56
57 }
58
59 System.out.println();
60
61 }
62
63 }
64
65
66
67 @Override
68
69 public Product createClone() {
70
71 Product product = null;
72
73 try {
74
75 product = (Product) clone();
76
77 } catch (CloneNotSupportedException e) {
78
79 e.printStackTrace();
80
81 }
82
83 return product;
84
85 }
86
87 }
88
89
90
91 import base.prototype.framework.Product;
92
93
94
95 /**
96
97 * @program: DesignPatterns
98
99 * @description: 打印三角形
100
101 * @author: Mr.Dai
102
103 * @create: 2018-05-28 21:47
104
105 **/
106
107 public class Triangle implements Product {
108
109
110
111 @Override
112
113 public void use(int len) {
114
115 for (int i = 0; i < len; i++) {
116
117 for (int j = i; j < len; j++) {
118
119 System.out.print(' ');
120
121 }
122
123
124
125 for (int j = 0; j < 2*i + 1; j++) {
126
127 System.out.print('*');
128
129 }
130
131 System.out.println();
132
133 }
134
135 }
136
137
138
139 @Override
140
141 public Product createClone() {
142
143 Product product=null;
144
145 try {
146
147 product=(Product)clone();
148
149 }catch (CloneNotSupportedException e){
150
151 e.printStackTrace();
152
153 }
154
155 return product;
156
157 }
158
159 }
160
161
- 结果
### 需要说明的是
> 面向对象的根本思想是作为组件复用:一旦出现的类名字就无法与该类区分开来,也就无法实现复用,如果不替换源代码 以java来说,重要的是当只有class文件的时候还能不能被复用,即使没有java文件也能够复用才是关键,
>要注意在顶层product 接口声明 集成的java.lang.cloneable。的接口是称之为标记接口只要这样下面雇用的具体的类才能调用具体的clone方法才不会抛出异常,,说明了 实现了cloneable 接口的实例是可以进行调用clone方法进行复制的,返回是一个新的实例,(clone内部所进行的处理是分配与要复制的实例同样大小的内存空间,是一盒字段复制 也很称 浅拷贝);也就是说 如在类中存在 数组 那么拷贝 只会拷贝数组的引用,不会对数组进行正的复制。如果你需要一个新的引用那么你需要 重写clone ,但是不要忘记 调用super。clone
### 相关设计模式
- Flyweight
可以生成一个与当前实例相同的的实例,使用Flyweight 模式可以在不同的地方使用同一个实例。
- Memento
提供保存当前实例状态,实现撤销与快照功能
- 与 Decorator模式
如果需要动态创建复杂的结构的实例,可以用prototype作为clone
- Command
复制Command模式中出现的额命令时,可以使用Prototype