概述
原型模式是一個創建型的模式。該模式有一個樣板實例,用戶從這個樣板對象中複製出一個內部屬性一致的對象,這個過程也就是俗稱的“克隆”。被複制的實例就是所稱的“原型”。
原型模式:用原型實例指定創建對象的種類,並通過拷貝這些原型創建新的對象
使用場景
類初始化需要消耗非常多的資源,包括數據、硬件資源等,通過原型拷貝避免這些消耗
通過new產生一個對象需要非常繁瑣的數據準備或訪問權限。這時可以使用原型拷貝
一個對象需要提供給其他對象調用者使用,而且各個調用者都需要修改其值,可以考慮通過原型模式拷貝多個對象供調用者使用,即保護性拷貝
原型模式的簡單實現
通過實現Cloneable接口:
首先創建一個文檔對象,即WordDocument,這個文檔中含有文字和圖片,編輯時在文檔副本上修改。
public class WordDocument implements Cloneable {
private String mText;
private ArrayList<String> mImages = new ArrayList<>();
public WordDocument() {
System.out.println("---------- WordDocument構造函數 -------------");
}
@Override
protected WordDocument clone() {
try {
WordDocument doc = (WordDocument) super.clone();
doc.mText = this.mText;
doc.mImages = this.mImages; // 淺拷貝
doc.mImages = (ArrayList<String>) mImages.clone(); // 深拷貝,引用類型
return doc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
public List<String> getmImages() {
return mImages;
}
public void addImage(String img) {
this.mImages.add(img);
}
}
淺拷貝: 也稱影子拷貝,副本並不是將原型所有字段都重新構造,而是引用。
深拷貝: 即拷貝對象時,對引用型的字段也要採用拷貝形式,並不是單純的引用
需要拷貝時調用clone()
WordDocument originDoc = new WordDocument();
originDoc.setmText("這是一篇文章");
originDoc.addImage("圖片1");
originDoc.addImage("圖片2");
WordDocument doc = originDoc.clone();
Android中的原型模式
- ArrayList:
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
- Intent:
@Override
public Object clone() {
return new Intent(this);
}
- …………
總結
使用原型模式可以解決構建複雜對象的資源消耗問題,能夠在某些場景提升創建對象的效率。還有一個重要用途就是保護性拷貝,也就是某個對象對外可能是隻讀的,爲了防止外部對這個只讀對象修改,通常可以返回一個對象拷貝的形式實現只讀的限制。
注意淺拷貝、深拷貝的區別
優點: 原型模式是在內存中二進制流的拷貝,要比直接new一個對象性能好很多,特別是在一個循環體內產生大量的對象時,原型模型可以更好地體現其優點
缺點: 直接在內存中拷貝,構造函數是不會執行的,實際開發要考慮這個潛在問題