原型設(shè)計(jì)模式
- 什么是原型設(shè)計(jì)模式
- 原型設(shè)計(jì)模式應(yīng)用場(chǎng)景
- 原型設(shè)計(jì)模式Demo
- 原型設(shè)計(jì)模式在Android源碼中的應(yīng)用
- 原型設(shè)計(jì)模式總結(jié)
參考:
- Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)
1.什么是原型設(shè)計(jì)模式
原型模式是一個(gè)創(chuàng)建型模式。用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。原型模式多用于創(chuàng)建復(fù)雜的或者構(gòu)造耗時(shí)的實(shí)例,因?yàn)樵谶@種情況下,復(fù)制一個(gè)已經(jīng)存在的實(shí)例會(huì)更高效。
2.原型設(shè)計(jì)模式應(yīng)用場(chǎng)景
- 類初始化需要消耗非常多的資源,這個(gè)資源包括數(shù)據(jù)、資源等,通過(guò)原型拷貝避免這些消耗
- 通過(guò)new 產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備和訪問(wèn)權(quán)限,這時(shí)可以使用原型模式
- 一個(gè)對(duì)象需要提供給其他對(duì)象進(jìn)行訪問(wèn)和操作,而且各個(gè)調(diào)用者都有可能修改其數(shù)據(jù),可以考慮使用原型拷貝多個(gè)對(duì)象供調(diào)用者使用,即保護(hù)性復(fù)制。
需要注意的是,通過(guò)實(shí)現(xiàn)Cloneable接口的原型模式在實(shí)現(xiàn) clone 函數(shù)構(gòu)造實(shí)例時(shí)并不一定比通過(guò)new 操作速度快,只有當(dāng)通過(guò)new 操作比較耗時(shí)或者說(shuō)成本比較高時(shí),通過(guò)clone 方法才能獲得效率上的提升。
3.原型設(shè)計(jì)模式Demo
這個(gè)例子中首先創(chuàng)建了一個(gè)文檔對(duì)象WordDocument,這個(gè)文檔中包含文字和圖片。用戶經(jīng)過(guò)了長(zhǎng)時(shí)間的編輯以后,打算對(duì)該文檔進(jìn)行進(jìn)一步的編輯,但是這個(gè)編輯后的文檔是否被采用并不確定。因此,為了安全起見(jiàn),用戶需要對(duì)當(dāng)前文檔拷貝一份,然后在文檔副本上進(jìn)行修改。
public class WordDocument implements Cloneable {
private String text;
private ArrayList<String> mImages = new ArrayList<>();
public WordDocument() {
}
@Override
protected WordDocument clone() {
try {
WordDocument wordDocument = (WordDocument) super.clone();
wordDocument.text = this.text;
wordDocument.mImages = this.mImages;
return wordDocument;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public void showDocument() {
System.out.println("Text :" + text);
for (String str : mImages) {
System.out.println("String :" + str);
}
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public ArrayList<String> getImages() {
return mImages;
}
public void setImages(ArrayList<String> mImages) {
this.mImages = mImages;
}
public void addImages(String image){
this.mImages.add(image);
}
}
通過(guò)WordDocument類模擬了文檔中的基本元素:文字和圖片。下面看Client 如何使用:
public class Client {
public static void main(String[] args){
System.out.println("--文檔內(nèi)容展示 begin--");
WordDocument wordDocument = new WordDocument();
wordDocument.setText("bob");
wordDocument.addImages("1");
wordDocument.showDocument();
System.out.println("--文檔內(nèi)容展示 end--");
System.out.println("--文檔復(fù)制內(nèi)容展示 begin--");
WordDocument wordDocument1 = wordDocument.clone();
wordDocument1.setText("bob1");
wordDocument1.addImages("44");
wordDocument1.showDocument();
System.out.println("--文檔復(fù)制內(nèi)容展示 end--");
System.out.println("--文檔內(nèi)容重新展示 begin--");
wordDocument.showDocument();
System.out.println("--文檔內(nèi)容重新展示 end--");
}
}
打印輸入結(jié)果:
--文檔內(nèi)容展示 begin--
Text :bob
String :1
--文檔內(nèi)容展示 end--
--文檔復(fù)制內(nèi)容展示 begin--
Text :bob1
String :1
String :44
--文檔復(fù)制內(nèi)容展示 end--
--文檔內(nèi)容重新展示 begin--
Text :bob
String :1
String :44
--文檔內(nèi)容重新展示 end--
wordDocument1是由wordDocument.clone() 創(chuàng)建的,即 wordDocument1 是 wordDocument的備份,而修改了wordDocument1的內(nèi)容也會(huì)影響wordDocument的內(nèi)容。上述原型模式的實(shí)現(xiàn)實(shí)際上只是一個(gè)淺拷貝,這份拷貝實(shí)際上并不是將原始文檔的所有字段都重新構(gòu)造了一份,而是副本文檔的字段引用原始文檔的字段。
需要修改clone 的方法,該為深拷貝
@Override
protected WordDocument clone() {
try {
WordDocument wordDocument = (WordDocument) super.clone();
wordDocument.text = this.text;
wordDocument.mImages = (ArrayList<String>) this.mImages.clone();
return wordDocument;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
打印輸入結(jié)果:
--文檔內(nèi)容展示 begin--
Text :bob
String :1
--文檔內(nèi)容展示 end--
--文檔復(fù)制內(nèi)容展示 begin--
Text :bob1
String :1
String :44
--文檔復(fù)制內(nèi)容展示 end--
--文檔內(nèi)容重新展示 begin--
Text :bob
String :1
--文檔內(nèi)容重新展示 end--
原型模式是比較簡(jiǎn)單的一個(gè)模式,它的核心問(wèn)題就是對(duì)原始對(duì)象進(jìn)行拷貝,為了減少錯(cuò)誤,建議每次都進(jìn)行深拷貝。
4.原型設(shè)計(jì)模式在Android源碼中的應(yīng)用
5.原型設(shè)計(jì)模式總結(jié)
5.1優(yōu)點(diǎn)
在內(nèi)存中二進(jìn)制流進(jìn)行拷貝,要比直接new 一個(gè)對(duì)象性能要好。
- 如果創(chuàng)建新的對(duì)象比較復(fù)雜時(shí),可以利用原型模式簡(jiǎn)化對(duì)象的創(chuàng)建過(guò)程,同時(shí)也能提高效率
- 可以使用深拷貝保持原始對(duì)象的狀態(tài)
- 原型模式提供了簡(jiǎn)化的創(chuàng)建結(jié)構(gòu)
5.2缺點(diǎn)
直接在內(nèi)存中進(jìn)行拷貝,是不會(huì)執(zhí)行構(gòu)造函數(shù)的,減少了約束。優(yōu)點(diǎn)是減少了約束,缺點(diǎn)也是減少了約束。
- 在實(shí)現(xiàn)深拷貝的時(shí)候可能需要比較復(fù)雜的代碼
- 需要為每一個(gè)類配備一個(gè)clone 方法,而且這個(gè)clone 方法需要對(duì)類的整體功能進(jìn)行考慮,這對(duì)全新的類來(lái)說(shuō)并不困難,但對(duì)已有的類進(jìn)行改造時(shí),并不是一件容易的事,必須修改其源代碼,違背了“開(kāi)閉原則”。