定義
用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi)值纱,并通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象
使用場(chǎng)景
(1)類(lèi)初始化需要消耗非常多的資源京景,包括數(shù)據(jù)星掰、硬件資源等。通過(guò)原型拷貝可以避免這些操作盼铁。
(2)通過(guò)new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或者訪問(wèn)權(quán)限粗蔚。
(3)一個(gè)對(duì)象需要提供給其他對(duì)象訪問(wèn),而且各個(gè)調(diào)用者可能都需要修改其值時(shí)饶火,可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者試用鹏控,即保護(hù)性拷貝
UML類(lèi)圖
關(guān)鍵點(diǎn)
(1)淺拷貝(影子拷貝):副本的屬性字段引用原型的屬性字段肤寝,即副本和原型相同的屬性字段指向內(nèi)存里同一個(gè)對(duì)象当辐。特別地,對(duì)于引用型的屬性鲤看,如ArrayList缘揪、String等,在兩個(gè)對(duì)象的任意一個(gè)里進(jìn)行修改【注意:修改并非賦值】义桂,另一個(gè)都會(huì)發(fā)生相應(yīng)變化找筝。
(2)深拷貝:副本的引用型屬性字段通過(guò)拷貝原型中對(duì)應(yīng)字段生成,而非直接引用慷吊。
(3)保護(hù)性拷貝:若希望某個(gè)對(duì)象對(duì)外只讀袖裕,防止外部對(duì)其修改,但實(shí)際調(diào)用過(guò)程中可能必須修改溉瓶,在希望不影響原數(shù)據(jù)的情況下急鳄,可以采用原型模式,以原對(duì)象為原型堰酿,對(duì)外提供其拷貝以供使用疾宏,無(wú)論怎么修改都不會(huì)影響到原對(duì)象,此做法稱(chēng)為保護(hù)性拷貝触创。
(4)原型模式產(chǎn)生新副本的過(guò)程中并沒(méi)有調(diào)用原型的構(gòu)造函數(shù)坎藐,所以如果構(gòu)造函數(shù)中有必須做的重要操作時(shí),請(qǐng)?jiān)赾lone()方法中完成哼绑,或勿使用原型模式
實(shí)現(xiàn)方式
淺拷貝:
public class ConcreatePrototype implements Cloneable{
? ? private Object a = null;
? ? private ConcreatePrototype(){}
? ? public void setA(Object a){
? ? ? ? this.a= a;
? ? }
? ? public Object getA(){
? ? ? ? return a;
? ? }
? ? @Override
? ? protected ConcreatePrototype clone(){
? ? ? ? try{
? ? ? ? ? ? Concreate Prototypetemp = (ConcreatePrototype) super.clone();
? ? ? ? ? ? temp.setA(this.a)
? ? ? ? ? ? return temp;
? ? ? ? }catch (Exception e){
? ? ? ? }
? ? ? ? return null;
? ? }
}
深拷貝:
public class ConcreatePrototype implements Cloneable{
? ? private Object a = null;
? ? private ArrayListlist = new ArrayList();
? ? private ConcreatePrototype(){}
? ? public void setA(Object a){
? ? ? ? this.a= a;
? ? }
? ? public Object getA(){
? ? ? ? return a;
? ? }
? ? public void setList(ArrayList list){
? ? ? ? this.list= list;
? ? }
? ? public ArrayListgetList(){
? ? ? ? returnlist;
? ? }
? ? public void addString(String string){
? ? ? ? list.add(string);
? ? }
? ? @Override
? ? protected ConcreatePrototype clone(){
? ? ? ? try{
? ? ? ? ? ? ConcreatePrototype temp = (ConcreatePrototype) super.clone();
? ? ? ? ? ? temp.a= a;
? ? ? ? ? ? temp.list= (ArrayList)list.clone();
? ? ? ? ? ? return temp;
? ? ? ? }catch (Exception e){
? ? ? ? }
? ? ? ? return null;
? ? }
}
調(diào)用:
pubic void class Test{
? ? public static void main(String [] args){
? ? ? ? ConcreatePrototype prototype = new ConcreatePrototype();
? ? ? ? prototype.setA("prototype");
? ? ? ? ConcreatePrototype newCopy = prototype.clone();
? ? ? ? newCopy.setA("copy");
? ? }
}
原型模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
原型模式是在內(nèi)存中二進(jìn)制流的拷貝顺饮,性能上要比調(diào)用構(gòu)造函數(shù)重新生成一個(gè)要好很多。特別是要再一個(gè)循環(huán)體內(nèi)產(chǎn)生大量對(duì)象的時(shí)候凌那,原型模式可以更好地體現(xiàn)其優(yōu)點(diǎn)。
缺點(diǎn)
由于構(gòu)造函數(shù)不執(zhí)行吟逝,所以對(duì)象的很多內(nèi)部約束并不會(huì)實(shí)現(xiàn)帽蝶,當(dāng)缺少這部分約束可能導(dǎo)致程序出錯(cuò)時(shí),在拷貝方法里就需要做完備的添加工作。
Android中的單例類(lèi)舉例
類(lèi)名:Intent(多數(shù)不用原型模式生成)
——2017.08.01