Skip to content

Commit b5b9eae

Browse files
committed
update schedule
1 parent 6f20750 commit b5b9eae

File tree

4 files changed

+258
-2
lines changed

4 files changed

+258
-2
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,20 @@
3434
| [组合模式](composite/tiny-times) | [tiny-times](https://github.com/tiny-times) | 撒丫子赶稿中 |
3535
| [装饰模式](decorator/tiny-times) | [tiny-times](https://github.com/tiny-times) | 撒丫子赶稿中 |
3636
| [享元模式](flyweight/lvtea0105) | [lvtea0105](https://github.com/lvtea0105) | 撒丫子赶稿中 |
37-
| [迭代器模式](iterator/haoxiqiang) | [Haoxiqiang](https://github.com/Haoxiqiang)| 待校对 |
37+
| [迭代器模式](iterator/haoxiqiang) | [Haoxiqiang](https://github.com/Haoxiqiang)| 完成 |
3838
| [责任链模式](chain-of-responsibility/AigeStudio) | [AigeStudio](https://github.com/AigeStudio)| 完成 |
3939
| [工厂方法模式](factory-method/AigeStudio) | [AigeStudio](https://github.com/AigeStudio)| 撒丫子赶稿中 |
4040
| [抽象工厂模式](abstract-factory/AigeStudio) | [AigeStudio](https://github.com/AigeStudio)| 撒丫子赶稿中 |
4141
| [状态模式](state/Thinan) | [Thinan](https://www.github.com/Thinan)| 撒丫子赶稿中 |
4242
| [命令模式](Command/lijunhuayc) | [lijunhuayc](https://github.com/lijunhuayc)| 匍匐前进ing |
4343
| [桥接模式](bridge/shen0834) | [shen0834](https://github.com/shen0834)| 撒丫子赶稿中 |
44+
| [原型模式](prototype/mr.simple) | [Mr.Simple](https://github.com/bboyfeiyu)| 待审核 |
45+
4446

4547

4648
## 目前无人认领的模式
4749
| 模式名 |
4850
| ------------- |
49-
| 桥接模式 |
5051
| 中介者模式 |
5152
| 备忘录模式 |
5253
| 原型模式 |

prototype/.DS_Store

6 KB
Binary file not shown.

prototype/mr.simple/.DS_Store

6 KB
Binary file not shown.

prototype/mr.simple/readme.md

+255
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
Android设计模式源码解析之原型模式
2+
====================================
3+
> 本文为 [Android 设计模式源码解析](https://github.com/simple-android-framework-exchange/android_design_patterns_analysis) 中 原型模式 分析
4+
> Android系统版本: 2.3
5+
> 分析者:[Mr.Simple](https://github.com/bboyfeiyu),分析状态:未完成,校对者:[Mr.Simple](https://github.com/bboyfeiyu),校对状态:完成
6+
7+
## 1. 模式介绍
8+
9+
### 模式的定义
10+
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
11+
12+
13+
### 模式的使用场景
14+
1. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗;
15+
2. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式;
16+
3. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
17+
18+
19+
## 2. UML类图
20+
![uml](images/prototype-uml.png)
21+
22+
### 角色介绍
23+
* Client : 客户端用户。
24+
* Prototype : 抽象类或者接口,声明具备clone能力。
25+
* ConcretePrototype : 具体的原型类.
26+
27+
28+
## 3. 模式的简单实现
29+
### 简单实现的介绍
30+
31+
下面我们以简单的文档拷贝为例来演示一下简单的原型模式模式。
32+
33+
### 实现源码
34+
35+
```java
36+
package com.dp.example.builder;
37+
38+
39+
package com.dp.example.prototype;
40+
41+
import java.util.ArrayList;
42+
import java.util.List;
43+
44+
/**
45+
* 文档类型, 扮演的是ConcretePrototype角色,而cloneable是代表prototype角色
46+
*
47+
* @author mrsimple
48+
*/
49+
public class WordDocument implements Cloneable {
50+
/**
51+
* 文本
52+
*/
53+
private String mText;
54+
/**
55+
* 图片名列表
56+
*/
57+
private ArrayList<String><string> mImages = new ArrayList<String><string>();
58+
59+
public WordDocument() {
60+
System.out.println("----------- WordDocument构造函数 -----------");
61+
}
62+
63+
/**
64+
* 克隆对象
65+
*/
66+
@Override
67+
protected WordDocument clone() {
68+
try {
69+
WordDocument doc = (WordDocument) super.clone();
70+
doc.mText = this.mText;
71+
doc.mImages = this.mImages;
72+
return doc;
73+
} catch (Exception e) {
74+
}
75+
76+
return null;
77+
}
78+
79+
public String getText() {
80+
return mText;
81+
}
82+
83+
public void setText(String mText) {
84+
this.mText = mText;
85+
}
86+
87+
public List<string> getImages() {
88+
return mImages;
89+
}
90+
91+
/**
92+
* @param img
93+
*/
94+
public void addImage(String img) {
95+
this.mImages.add(img);
96+
}
97+
98+
/**
99+
* 打印文档内容
100+
*/
101+
public void showDocument() {
102+
System.out.println("----------- Word Content Start -----------");
103+
System.out.println("Text : " + mText);
104+
System.out.println("Images List: ");
105+
for (String imgName : mImages) {
106+
System.out.println("image name : " + imgName);
107+
}
108+
System.out.println("----------- Word Content End -----------");
109+
}
110+
}
111+
```
112+
113+
通过WordDocument类模拟了word文档中的基本元素,即文字和图片。WordDocument的在该原型模式示例中扮演的角色为ConcretePrototype, 而Cloneable的角色则为Prototype。WordDocument实现了clone方法以实现对象克隆。下面我们看看Client端的使用 :
114+
115+
```java
116+
public class Client {
117+
public static void main(String[] args) {
118+
WordDocument originDoc = new WordDocument();
119+
originDoc.setText("这是一篇文档");
120+
originDoc.addImage("图片1");
121+
originDoc.addImage("图片2");
122+
originDoc.addImage("图片3");
123+
originDoc.showDocument();
124+
125+
WordDocument doc2 = originDoc.clone();
126+
doc2.showDocument();
127+
128+
doc2.setText("这是修改过的Doc2文本");
129+
doc2.showDocument();
130+
131+
originDoc.showDocument();
132+
}
133+
134+
}
135+
```
136+
输出结果如下 :
137+
![result](images/result.png)
138+
139+
可以看到,doc2是通过originDoc.clone()创建的,并且doc2第一次输出的时候和originDoc输出是一样的。即doc2是originDoc的一份拷贝,他们的内容是一样的,而doc2修改了文本内容以后并不会影响originDoc的文本内容。需要注意的是通过clone拷贝对象的时候并不会执行构造函数!
140+
141+
142+
### 浅拷贝和深拷贝
143+
将main函数的内容修改为如下 :
144+
145+
```java
146+
public static void main(String[] args) {
147+
WordDocument originDoc = new WordDocument();
148+
originDoc.setText("这是一篇文档");
149+
originDoc.addImage("图片1");
150+
originDoc.addImage("图片2");
151+
originDoc.addImage("图片3");
152+
originDoc.showDocument();
153+
154+
WordDocument doc2 = originDoc.clone();
155+
156+
doc2.showDocument();
157+
158+
doc2.setText("这是修改过的Doc2文本");
159+
doc2.addImage("哈哈.jpg");
160+
doc2.showDocument();
161+
162+
originDoc.showDocument();
163+
}
164+
```
165+
166+
输出结果如下 :
167+
![result](images/result-2.png)
168+
细心的朋友可能发现了,在doc2添加了一张名为"哈哈.jpg"的照片,但是却也显示在originDoc中?这是怎么回事呢? 其实学习过C++的朋友都知道,这是因为上文中WordDocument的clone方法中只是简单的进行浅拷贝,引用类型的新对象doc2的mImages只是单纯的指向了this.mImages引用,而并没有进行拷贝。doc2的mImages添加了新的图片,实际上也就是往originDoc里添加了新的图片,所以originDoc里面也有"哈哈.jpg" 。那如何解决这个问题呢? 那就是采用深拷贝,即在拷贝对象时,对于引用型的字段也要采用拷贝的形式,而不是单纯引用的形式。示例如下 :
169+
170+
```java
171+
/**
172+
* 克隆对象
173+
*/
174+
@Override
175+
protected WordDocument clone() {
176+
try {
177+
WordDocument doc = (WordDocument) super.clone();
178+
doc.mText = this.mText;
179+
// doc.mImages = this.mImages;
180+
doc.mImages = (ArrayList<String>) this.mImages.clone();
181+
return doc;
182+
} catch (Exception e) {
183+
}
184+
185+
return null;
186+
}
187+
```
188+
189+
如上代码所示,将doc.mImages指向this.mImages的一份拷贝, 而不是this.mImages本身,这样在doc2添加图片时并不会影响originDoc,如图所示 :
190+
![result](images/result-3.png)
191+
192+
193+
## Android源码中的模式实现
194+
在Android源码中,我们以熟悉的Intent来分析源码中的原型模式。简单示例如下 :
195+
196+
```java
197+
Uri uri = Uri.parse("smsto:0800000123");
198+
Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri);
199+
shareIntent.putExtra("sms_body", "The SMS text");
200+
201+
Intent intent = (Intent)shareIntent.clone() ;
202+
startActivity(intent);
203+
```
204+
205+
结果如下 :
206+
207+
![result](images/sms.png)
208+
209+
可以看到,我们通过shareIntent.clone方法拷贝了一个对象intent, 然后执行startActivity(intent), 随即就进入了短信页面,号码为0800000123,文本内容为The SMS text,即这些内容都与shareIntent一致。
210+
211+
```java
212+
@Override
213+
public Object clone() {
214+
return new Intent(this);
215+
}
216+
217+
/**
218+
* Copy constructor.
219+
*/
220+
public Intent(Intent o) {
221+
this.mAction = o.mAction;
222+
this.mData = o.mData;
223+
this.mType = o.mType;
224+
this.mPackage = o.mPackage;
225+
this.mComponent = o.mComponent;
226+
this.mFlags = o.mFlags;
227+
if (o.mCategories != null) {
228+
this.mCategories = new ArraySet<String>(o.mCategories);
229+
}
230+
if (o.mExtras != null) {
231+
this.mExtras = new Bundle(o.mExtras);
232+
}
233+
if (o.mSourceBounds != null) {
234+
this.mSourceBounds = new Rect(o.mSourceBounds);
235+
}
236+
if (o.mSelector != null) {
237+
this.mSelector = new Intent(o.mSelector);
238+
}
239+
if (o.mClipData != null) {
240+
this.mClipData = new ClipData(o.mClipData);
241+
}
242+
}
243+
```
244+
245+
可以看到,clone方法实际上在内部调用了new Intent(this); 这就和C++中的拷贝构造函数完全一致了,而且是深拷贝。由于该模式比较简单,就不做太多说明。
246+
247+
248+
## 4. 杂谈
249+
### 优点与缺点
250+
* 优点
251+
原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
252+
253+
* 缺点
254+
这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发当中应该注意这个潜在的问题。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。
255+

0 commit comments

Comments
 (0)