wordpress自適應(yīng)模版seow
文章目錄
- 設(shè)計(jì)模式概述
- 1、原型模式
- 2、原型模式的使用場景
- 3、優(yōu)點(diǎn)
- 4、缺點(diǎn)
- 5、主要角色
- 6、代碼示例
- 7、總結(jié)
- 題外話關(guān)于使用序列化實(shí)現(xiàn)深拷貝
設(shè)計(jì)模式概述
創(chuàng)建型模式:工廠方法、抽象方法、建造者、原型、單例。
結(jié)構(gòu)型模式有:適配器、橋接、組合、裝飾器、外觀、享元、代理。
行為型模式有:責(zé)任鏈、命令、解釋器、迭代器、中介、備忘錄、觀察者、狀態(tài)、策略、模板方法、訪問者。
常用設(shè)計(jì)模式:
單例模式、工廠模式、代理模式、策略模式&模板模式、門面模式、責(zé)任鏈模式、裝飾器模式、組合模式、builder模式。
1、原型模式
- 原型模式(Prototype Pattern)是用于創(chuàng)建重復(fù)的對象,同時又能保證性能。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式之一。
- 這種模式是實(shí)現(xiàn)了一個原型接口,該接口用于創(chuàng)建當(dāng)前對象的克隆。當(dāng)直接創(chuàng)建對象的代價(jià)比較大時,則采用這種模式。
2、原型模式的使用場景
- 在需要一個類的大量對象的時候,使用原型模式是最佳選擇,因?yàn)樵湍J绞窃趦?nèi)存中對這個對象進(jìn)行拷貝,要比直接new這個對象性能要好很多,在這種情況下,需要的對象越多,原型模式體現(xiàn)出的優(yōu)點(diǎn)越明顯。
- 如果一個對象的初始化需要很多其他對象的數(shù)據(jù)準(zhǔn)備或其他資源的繁瑣計(jì)算,那么可以使用原型模式。
- 當(dāng)需要一個對象的大量公共信息,少量字段進(jìn)行個性化設(shè)置的時候,也可以使用原型模式拷貝出現(xiàn)有對象的副本進(jìn)行加工處理。
3、優(yōu)點(diǎn)
- 原型模式允許在運(yùn)行時動態(tài)改變具體的實(shí)現(xiàn)類型。原型模式可以在運(yùn)行期間,由客戶來注冊符合原型接口的實(shí)現(xiàn)類型,也可以動態(tài)地改變具體的實(shí)現(xiàn)類型,看起來接口沒有任何變化,但其實(shí)運(yùn)行的已經(jīng)是另外一個類實(shí)例了。因?yàn)榭寺∫粋€原型就類似于實(shí)例化一個類。
4、缺點(diǎn)
- 原型模式最主要的缺點(diǎn)是每一個類都必須配備一個克隆方法。配備克隆方法需要對類的功能進(jìn)行通盤考慮,這對于全新的類來說不是很難,而對于已經(jīng)有的類不一定很容易,特別是當(dāng)一個類引用不支持序列化的間接對象,或者引用含有循環(huán)結(jié)構(gòu)的時候。
5、主要角色
(1)客戶(Client)角色:客戶類提出創(chuàng)建對象的請求。
(2)抽象原型(Prototype)角色:這是一個抽象角色,通常由一個Java接口或Java抽象類實(shí)現(xiàn)。此角色給出所有的具體原型類所需的接口。
(3)具體原型(Concrete Prototype)角色:被復(fù)制的對象。此角色需要實(shí)現(xiàn)抽象的原型角色所要求的接口。
6、代碼示例
1)UML圖
2)源代碼
(1)抽象原型角色
public interface Prototype{/*** 克隆自身的方法* @return 一個從自身克隆出來的對象*/public Object clone();
}
(2)具體原型角色
public class ConcretePrototype1 implements Prototype {public Prototype clone(){//最簡單的克隆,新建一個自身對象,由于沒有屬性就不再復(fù)制值了Prototype prototype = new ConcretePrototype1();return prototype;}
}public class ConcretePrototype2 implements Prototype {public Prototype clone(){//最簡單的克隆,新建一個自身對象,由于沒有屬性就不再復(fù)制值了Prototype prototype = new ConcretePrototype2();return prototype;}
}
(3)客戶端角色
public class Client {public static void main(String[]args){try{Prototype p1 = new ConcretePrototype1();//獲取原型來創(chuàng)建對象Prototype p2 = p1.clone();//有人動態(tài)的切換了實(shí)現(xiàn)Prototype p3 = new ConcretePrototype2();Prototype p4 = p3.clone();}catch(Exception e){e.printStackTrace();}}
}
}
7、總結(jié)
- 這種情況就是淺拷貝,java只拷貝你指定的對象,至于你指定的對象里面的別的對象,它不拷貝,還是把引用給你,共享變量,這是一種非常不安全的方式,需要特別注意。
- 內(nèi)部的數(shù)組和引用對象不會拷貝,其他的原始基本類型和String類型會被拷貝。
- 如果需要可以使用深拷貝,結(jié)合具體對象的情況進(jìn)行處理(可以自己實(shí)現(xiàn)深拷貝邏輯;或者利用序列化和反序列化實(shí)現(xiàn)深拷貝,前提是所有需要復(fù)制的對象都需要實(shí)現(xiàn)java.io.Serializable接口。)
題外話關(guān)于使用序列化實(shí)現(xiàn)深拷貝
利用序列化實(shí)現(xiàn)深度克隆:
- 把對象寫到流里的過程是序列化(Serialization)過程;而把對象從流中讀出來的過程則叫反序列化(Deserialization)過程。應(yīng)當(dāng)指出的是,寫到流里的是對象的一個拷貝,而原對象仍然存在于JVM里面。
- 在Java語言里深度克隆一個對象,常??梢韵仁箤ο髮?shí)現(xiàn)Serializable接口,然后把對象(實(shí)際上只是對象的拷貝)寫到一個流里(序列化),再從流里讀回來(反序列化),便可以重建對象。
public Object deepClone() throws IOException, ClassNotFoundException{//將對象寫到流里ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);//從流里讀回來ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return ois.readObject();}
-
這樣做的前提就是對象以及對象內(nèi)部所有引用到的對象都是可序列化的,否則,就需要仔細(xì)考察那些不可序列化的對象可否設(shè)成transient,從而將之排除在復(fù)制過程之外。
-
淺度克隆顯然比深度克隆更容易實(shí)現(xiàn),因?yàn)镴ava語言的所有類都會繼承一個clone()方法,而這個clone()方法所做的正式淺度克隆。