一贞远、介紹及定義
①介紹:原型模式是一種創(chuàng)建型的模式悦即。原型兩個(gè)字表明了該模式應(yīng)該有一個(gè)樣板實(shí)例赴捞,用戶從這個(gè)樣板實(shí)例中復(fù)制出
一個(gè)內(nèi)部屬性一致的對(duì)象逼裆,這個(gè)過程通俗的講就是“克隆”。這個(gè)被復(fù)制的實(shí)例就稱為“原型”赦政。
②定義:用原型實(shí)例指定創(chuàng)建對(duì)象的種類胜宇,并通過拷貝這些原型創(chuàng)建新的對(duì)象。
③場(chǎng)景:用于創(chuàng)建復(fù)雜的和耗時(shí)的實(shí)例
注:通過實(shí)現(xiàn)Cloneable接口的原型模式在調(diào)用clone函數(shù)構(gòu)造實(shí)例時(shí)并不一定比new構(gòu)建速度快恢着,只有通過new對(duì)象成本較高或者耗時(shí)時(shí)桐愉,才會(huì)使用clone構(gòu)建對(duì)象。
二掰派、UML類圖
三从诲、案例
創(chuàng)建
public class WordDocument implements Cloneable{
private String name;
private ArrayList<String> mlist=new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<String> getMlist() {
return mlist;
}
public void addString(String text) {
this.mlist.add(text);
}
@Override
protected WordDocument clone() {
try {
WordDocument wordDocument= (WordDocument) super.clone();
wordDocument.name = this.name;
wordDocument.mlist=this.mlist;
return wordDocument;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void showDocument(){
Log.e("TAG","==============start==============");
Log.e("TAG","name====="+name);
for (String string:mlist){
Log.e("TAG","text====="+string);
}
Log.e("TAG","==============end=================");
}
}
使用
WordDocument wordDocument = new WordDocument();
wordDocument.setName("張三");
wordDocument.addString("張三");
wordDocument.addString("張三");
wordDocument.addString("張三");
wordDocument.showDocument();
WordDocument clone = wordDocument.clone();
clone.showDocument();
clone.setName("李四");
clone.showDocument();
wordDocument.showDocument();
打印結(jié)果
四、淺拷貝和深拷貝
上述例子其實(shí)是一個(gè)淺拷貝靡羡,也稱影子拷貝系洛,這種拷貝并不是將原始數(shù)據(jù)字段拷貝了一份,只是引用了原始數(shù)據(jù)對(duì)象字段略步。只是指向了一個(gè)相同的內(nèi)存地址描扯。
有下面打印
WordDocument wordDocument = new WordDocument();
wordDocument.setName("張三");
wordDocument.addString("張三");
wordDocument.addString("張三");
wordDocument.addString("張三");
wordDocument.showDocument();
WordDocument clone = wordDocument.clone();
clone.showDocument();
clone.setName("李四");
clone.addString("李四");
clone.addString("李四");
clone.addString("李四");
clone.showDocument();
wordDocument.showDocument();
打印結(jié)果發(fā)現(xiàn)最后兩次一樣,修改一個(gè)另一個(gè)也變纳像,所以這就是淺拷貝荆烈,解決可以采用深拷貝,改變一下方法如下
@Override
protected WordDocument clone() {
try {
WordDocument wordDocument= (WordDocument) super.clone();
wordDocument.name = this.name.clone();
wordDocument.mlist= (ArrayList<String>) this.mlist.clone();
return wordDocument;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
五竟趾、源碼中原型設(shè)計(jì)模式
①ArrayList中的使用
上面例子可知ArrayList也有clone()方法,如下
@Override
public Object clone() {
try {
ArrayList<?> result = (ArrayList<?>) super.clone();
result.array = array.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
其實(shí)該方法很簡(jiǎn)單先克隆本身再克隆對(duì)象中元素宫峦,為啥size沒有克虏砻薄?因?yàn)閟ize為整形导绷,并不是一個(gè)對(duì)象犀勒,clone()為Object中方法,不是一個(gè)引用類型,是值類型贾费,不需要克隆钦购。
②Intent中的使用
Intent intent = new Intent();
intent.clone();
查看源碼
@Override
public Object clone() {
return new Intent(this);
}
private Intent(Intent o, boolean all) {
this.mAction = o.mAction;
this.mData = o.mData;
this.mType = o.mType;
this.mPackage = o.mPackage;
this.mComponent = o.mComponent;
if (o.mCategories != null) {
this.mCategories = new ArraySet<String>(o.mCategories);
}
}