UML關(guān)系簡(jiǎn)單介紹
UML簡(jiǎn)單使用的介紹
創(chuàng)建型設(shè)計(jì)模式
Android設(shè)計(jì)模式-單例模式
Android設(shè)計(jì)模式-工廠模式
Android設(shè)計(jì)模式-抽象工廠模式
Android設(shè)計(jì)模式-建造者模式
Android設(shè)計(jì)模式-原型模式
結(jié)構(gòu)型設(shè)計(jì)模式
Android設(shè)計(jì)模式-代理模式
Android設(shè)計(jì)模式-裝飾模式
Android設(shè)計(jì)模式-適配器模式
Android設(shè)計(jì)模式-組合模式
Android設(shè)計(jì)模式-門(mén)面模式
Android設(shè)計(jì)模式-橋接模式
Android設(shè)計(jì)模式-享元模式
行為型設(shè)計(jì)模式
Android設(shè)計(jì)模式-策略模式
Android設(shè)計(jì)模式-命令模式
Android設(shè)計(jì)模式-責(zé)任鏈模式
Android設(shè)計(jì)模式-模版方法模式
Android設(shè)計(jì)模式-迭代器模式
Android設(shè)計(jì)模式-觀察者模式
Android設(shè)計(jì)模式-備忘錄模式
Android設(shè)計(jì)模式-中介者模式
Android設(shè)計(jì)模式-訪問(wèn)者模式
Android設(shè)計(jì)模式-狀態(tài)模式
Android設(shè)計(jì)模式-解釋器模式
1.定義
用原型實(shí)例指定創(chuàng)建對(duì)象的類型,并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象臼婆。
2.原型模式UML圖
原型模式的核心就在于clone()這個(gè)方法趋箩,這個(gè)方法是在Object類下拙徽,java中所有類的根源磨隘。蒸其。侵歇。使用原型模式的時(shí)候,需要用 Cloneable接口來(lái)進(jìn)行標(biāo)記癣疟。
3.具體實(shí)現(xiàn)
3.1 抽象原型類一般不需要寫(xiě)
3.2具體原型類
public class TestPrototype implements Cloneable {
private int i;
private ArrayList<String> list=new ArrayList<>();
public TestPrototype() {
System.out.println("執(zhí)行了構(gòu)造函數(shù)");
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public ArrayList<String> getList() {
return list;
}
public void addList(String s) {
list.add(s);
}
/**
* 同一個(gè)包下挣柬,可以使用protected,跨包則改為public
* @return
* @throws
*/
@Override
public Object clone() throws CloneNotSupportedException {
System.out.println("執(zhí)行了復(fù)制");
return super.clone();
}
}
同一個(gè)包下睛挚,可以使用protected邪蛔,跨包則改為public
3.3場(chǎng)景類調(diào)用
public class MyClass {
public static void main(String args[]) {
TestPrototype testPrototype=new TestPrototype();
testPrototype.setI(10);
testPrototype.addList("111");
System.out.println("testPrototype對(duì)象中l(wèi)ist為"+testPrototype.getList());
TestPrototype testClone=null;
try {
testClone= (TestPrototype) testPrototype.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
if (null!=testClone){
testClone.addList("222");
System.out.println("復(fù)制的對(duì)象中i為"+testClone.getI());
System.out.println("復(fù)制的對(duì)象中l(wèi)ist為"+testClone.getList());
System.out.println("testPrototype對(duì)象中l(wèi)ist為"+testPrototype.getList());
testClone.setI(20);
System.out.println("testPrototype對(duì)象中i為"+testPrototype.getI());
}
}
}
3.4打印結(jié)果
執(zhí)行了構(gòu)造函數(shù)
testPrototype對(duì)象中l(wèi)ist為[111]
執(zhí)行了復(fù)制
復(fù)制的對(duì)象中i為10
復(fù)制的對(duì)象中l(wèi)ist為[111, 222]
testPrototype對(duì)象中l(wèi)ist為[111, 222]
testPrototype對(duì)象中i為10
4.總結(jié)
- 從上圖的打印結(jié)果中,可以看出扎狱,通過(guò)new創(chuàng)建的對(duì)象侧到,會(huì)走他的構(gòu)造函數(shù),而通過(guò)clone創(chuàng)建的對(duì)象淤击,是不會(huì)走構(gòu)造函數(shù)的匠抗。
具體原因是因?yàn)?strong>Object類的clone方法的原理是從堆內(nèi)存中以二進(jìn)制流的方式進(jìn)行拷貝,重新分配一個(gè)內(nèi)存塊 - 修改復(fù)制后對(duì)象的i值污抬,原對(duì)象中的值不變汞贸,而修改復(fù)制后對(duì)象的list值,原對(duì)象中的值也發(fā)生了改變印机。
原因在于深拷貝和淺拷貝前面的例子就是一個(gè)淺拷貝矢腻,兩個(gè)對(duì)象共享了list這個(gè)變量《幔可能存在這個(gè)問(wèn)題的變量比如數(shù)組踏堡,引用對(duì)象猎唁,其他基本數(shù)據(jù)類型加上string是不會(huì)有這種問(wèn)題的咒劲。
將上面的例子改動(dòng)幾行代碼顷蟆,就能實(shí)現(xiàn)深拷貝
重寫(xiě)具體原型類中的clone方法為
@Override
public TestPrototype clone() throws CloneNotSupportedException {
TestPrototype prototype=null;
prototype= (TestPrototype) super.clone();
prototype.list= (ArrayList<String>) this.list.clone();
System.out.println("執(zhí)行了復(fù)制");
return prototype;
}
此時(shí)即可防止出現(xiàn)淺拷貝的問(wèn)題。還是剛才的代碼腐魂,打印數(shù)據(jù)帐偎,結(jié)果為
執(zhí)行了構(gòu)造函數(shù)
testPrototype對(duì)象中l(wèi)ist為[111]
執(zhí)行了復(fù)制
復(fù)制的對(duì)象中i為10
復(fù)制的對(duì)象中l(wèi)ist為[111, 222]
testPrototype對(duì)象中l(wèi)ist為[111]
testPrototype對(duì)象中i為10
深拷貝還有另一種實(shí)現(xiàn)方式就是通過(guò)自己寫(xiě)二進(jìn)制流來(lái)操作對(duì)象,然后實(shí)現(xiàn)對(duì)象的深拷貝蛔屹。
注意:深拷貝和淺拷貝建議不要混合使用削樊,特別是涉及類的繼承的時(shí)候,父類有多個(gè)引用的情況就非常復(fù)雜兔毒,建議的方案是深拷貝和淺拷貝分開(kāi)實(shí)現(xiàn)漫贞。
- 要使用clone方法,類的成員變量上不要添加final關(guān)鍵字育叁,這倆是有沖突的迅脐。