原型設(shè)計(jì)模式


I. 原型模式的定義

原型(Prototype)模式的定義如下:用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過(guò)復(fù)制該原型對(duì)象來(lái)創(chuàng)建一個(gè)和原型相同或相似的新對(duì)象。在這里,原型實(shí)例指定了要?jiǎng)?chuàng)建的對(duì)象的種類(lèi)。用這種方式創(chuàng)建對(duì)象非常高效,根本無(wú)須知道對(duì)象創(chuàng)建的細(xì)節(jié)。


II. 原型模式的應(yīng)用場(chǎng)景

  • 對(duì)象之間相同或相似,即只是個(gè)別的幾個(gè)屬性不同的時(shí)候。
  • 創(chuàng)建對(duì)象成本較大,例如初始化時(shí)間長(zhǎng),占用CPU太多,或者占用網(wǎng)絡(luò)資源太多等,需要優(yōu)化資源。
  • 創(chuàng)建一個(gè)對(duì)象需要繁瑣的數(shù)據(jù)準(zhǔn)備或訪問(wèn)權(quán)限等,需要提高性能或者提高安全性。
  • 系統(tǒng)中大量使用該類(lèi)對(duì)象,且各個(gè)調(diào)用者都需要給它的屬性重新賦值。


III. 最簡(jiǎn)單的原型模式

  • 給bean類(lèi)實(shí)現(xiàn)Cloneable接口并實(shí)現(xiàn)clone方法 (該方式屬于淺拷貝)
public class Sheep implements Cloneable{

    private String name;
    private Integer age;
    /* 省略get/set/constructor */
    @Override
    protected Object clone(){
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sheep;
    }
}


IV. 淺拷貝與深拷貝

  • 淺拷貝 : 創(chuàng)建一個(gè)新對(duì)象,新對(duì)象的屬性和原來(lái)對(duì)象完全相同,對(duì)于非基本類(lèi)型屬性,仍指向原有屬性所指向的對(duì)象的內(nèi)存地址。[ 比如sheep類(lèi)中添加一個(gè)Sheep friend 屬性,copy后,sheep1與sheep指向的friend是同一個(gè)地址,此時(shí)調(diào)用sheep.friend.setName(),sheep1中的值也會(huì)改變]
  • 深拷貝 : 創(chuàng)建一個(gè)新對(duì)象,屬性中引用的其他對(duì)象也會(huì)被克隆,不再指向原有對(duì)象地址。


V. 深拷貝的兩種實(shí)現(xiàn)

1. 首先準(zhǔn)備這樣2個(gè)類(lèi),均實(shí)現(xiàn)Serializable & Cloneable

示例類(lèi)UML

方式一 : 對(duì)引用類(lèi)型逐個(gè)處理 (不推薦使用)

    @Override
    protected Object clone() {
        DeepCopy deep = null;
        try {
            deep = (DeepCopy) super.clone();
            DeepCopyInner deepCopyInner = (DeepCopyInner) deep.getDeepCopyInner().clone();
            deep.setDeepCopyInner(deepCopyInner);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return deep;
    }

方式二 : 將整個(gè)對(duì)象序列化 (推薦使用)

    @Override
    protected Object clone() {

        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); // 將當(dāng)前對(duì)象以對(duì)象流的方式輸出

            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray()); // 將oos的輸出讀入
            ois = new ObjectInputStream(bis);
            DeepCopy deep = (DeepCopy) ois.readObject();

            return deep;
        } catch (Exception e) {
            e.printStackTrace();
            // 出現(xiàn)異常返回null
            return null;
        } finally {
            close(bos, oos, bis, ois);
        }

    }
    // 關(guān)閉
    private void close(ByteArrayOutputStream bos, ObjectOutputStream oos, ByteArrayInputStream bis, ObjectInputStream ois){
        try {
            bos.close();
            oos.close();
            bis.close();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


VI. 總結(jié)

優(yōu)點(diǎn):

  • 克隆對(duì)象比new一個(gè)對(duì)象的速度更快,開(kāi)銷(xiāo)更少
  • 可以使用深拷貝保存對(duì)象在某一時(shí)刻的狀態(tài),方便撤銷(xiāo)操作

缺點(diǎn):

  • 需要為每個(gè)類(lèi)配置clone方法
  • clone 方法位于類(lèi)的內(nèi)部,當(dāng)對(duì)已有類(lèi)進(jìn)行改造的時(shí)候,需要修改代碼,違背了開(kāi)閉原則。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),并通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。 (1)原型模式實(shí)現(xiàn) 實(shí)現(xiàn)Cloneable接口;重...
    kjy_112233閱讀 173評(píng)論 0 0
  • 一、介紹及定義 ①介紹:原型模式是一種創(chuàng)建型的模式。原型兩個(gè)字表明了該模式應(yīng)該有一個(gè)樣板實(shí)例,用戶從這個(gè)樣板實(shí)例中...
    Ayres閱讀 930評(píng)論 0 2
  • 設(shè)計(jì)模式專(zhuān)欄 設(shè)計(jì)模式專(zhuān)欄 1.定義: 原型模式(Prototype Pattern)是用于創(chuàng)建重復(fù)的對(duì)象,同時(shí)又...
    OneXzgj閱讀 462評(píng)論 1 1
  • 原型設(shè)計(jì)模式 什么是原型設(shè)計(jì)模式 原型設(shè)計(jì)模式應(yīng)用場(chǎng)景 原型設(shè)計(jì)模式Demo 原型設(shè)計(jì)模式在Android源碼中的...
    duqiuke閱讀 432評(píng)論 0 1
  • 漸變的面目拼圖要我怎么拼? 我是疲乏了還是投降了? 不是不允許自己墜落, 我沒(méi)有滴水不進(jìn)的保護(hù)膜。 就是害怕變得面...
    悶熱當(dāng)乘涼閱讀 4,463評(píng)論 0 13

友情鏈接更多精彩內(nèi)容