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

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

  1. 什么是原型設(shè)計(jì)模式
  2. 原型設(shè)計(jì)模式應(yīng)用場(chǎng)景
  3. 原型設(shè)計(jì)模式Demo
  4. 原型設(shè)計(jì)模式在Android源碼中的應(yīng)用
  5. 原型設(shè)計(jì)模式總結(jié)

參考

  1. Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)

1.什么是原型設(shè)計(jì)模式

原型模式是一個(gè)創(chuàng)建型模式。用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。原型模式多用于創(chuàng)建復(fù)雜的或者構(gòu)造耗時(shí)的實(shí)例,因?yàn)樵谶@種情況下,復(fù)制一個(gè)已經(jīng)存在的實(shí)例會(huì)更高效。

2.原型設(shè)計(jì)模式應(yīng)用場(chǎng)景

  1. 類初始化需要消耗非常多的資源,這個(gè)資源包括數(shù)據(jù)、資源等,通過(guò)原型拷貝避免這些消耗
  2. 通過(guò)new 產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備和訪問(wèn)權(quán)限,這時(shí)可以使用原型模式
  3. 一個(gè)對(duì)象需要提供給其他對(duì)象進(jìn)行訪問(wèn)和操作,而且各個(gè)調(diào)用者都有可能修改其數(shù)據(jù),可以考慮使用原型拷貝多個(gè)對(duì)象供調(diào)用者使用,即保護(hù)性復(fù)制。

需要注意的是,通過(guò)實(shí)現(xiàn)Cloneable接口的原型模式在實(shí)現(xiàn) clone 函數(shù)構(gòu)造實(shí)例時(shí)并不一定比通過(guò)new 操作速度快,只有當(dāng)通過(guò)new 操作比較耗時(shí)或者說(shuō)成本比較高時(shí),通過(guò)clone 方法才能獲得效率上的提升。

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

這個(gè)例子中首先創(chuàng)建了一個(gè)文檔對(duì)象WordDocument,這個(gè)文檔中包含文字和圖片。用戶經(jīng)過(guò)了長(zhǎng)時(shí)間的編輯以后,打算對(duì)該文檔進(jìn)行進(jìn)一步的編輯,但是這個(gè)編輯后的文檔是否被采用并不確定。因此,為了安全起見(jiàn),用戶需要對(duì)當(dāng)前文檔拷貝一份,然后在文檔副本上進(jìn)行修改。

public class WordDocument implements Cloneable {

    private String text;
    private ArrayList<String> mImages = new ArrayList<>();

    public WordDocument() {
    }

    @Override
    protected WordDocument clone() {
        try {
            WordDocument wordDocument = (WordDocument) super.clone();
            wordDocument.text = this.text;
            wordDocument.mImages = this.mImages;
            return wordDocument;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void showDocument() {
        System.out.println("Text :" + text);
        for (String str : mImages) {
            System.out.println("String :" + str);
        }
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public ArrayList<String> getImages() {
        return mImages;
    }

    public void setImages(ArrayList<String> mImages) {
        this.mImages = mImages;
    }

    public void addImages(String image){
        this.mImages.add(image);
    }

}

通過(guò)WordDocument類模擬了文檔中的基本元素:文字和圖片。下面看Client 如何使用:

public class Client {

    public static void main(String[] args){
        System.out.println("--文檔內(nèi)容展示 begin--");
        WordDocument wordDocument = new WordDocument();
        wordDocument.setText("bob");
        wordDocument.addImages("1");
        wordDocument.showDocument();
        System.out.println("--文檔內(nèi)容展示 end--");


        System.out.println("--文檔復(fù)制內(nèi)容展示 begin--");
        WordDocument wordDocument1 =  wordDocument.clone();
        wordDocument1.setText("bob1");
        wordDocument1.addImages("44");
        wordDocument1.showDocument();
        System.out.println("--文檔復(fù)制內(nèi)容展示 end--");


        System.out.println("--文檔內(nèi)容重新展示 begin--");
        wordDocument.showDocument();
        System.out.println("--文檔內(nèi)容重新展示 end--");
    }
}

打印輸入結(jié)果:

--文檔內(nèi)容展示 begin--
Text :bob
String :1
--文檔內(nèi)容展示 end--
--文檔復(fù)制內(nèi)容展示 begin--
Text :bob1
String :1
String :44
--文檔復(fù)制內(nèi)容展示 end--
--文檔內(nèi)容重新展示 begin--
Text :bob
String :1
String :44
--文檔內(nèi)容重新展示 end--

wordDocument1是由wordDocument.clone() 創(chuàng)建的,即 wordDocument1 是 wordDocument的備份,而修改了wordDocument1的內(nèi)容也會(huì)影響wordDocument的內(nèi)容。上述原型模式的實(shí)現(xiàn)實(shí)際上只是一個(gè)淺拷貝,這份拷貝實(shí)際上并不是將原始文檔的所有字段都重新構(gòu)造了一份,而是副本文檔的字段引用原始文檔的字段。

需要修改clone 的方法,該為深拷貝

    @Override
    protected WordDocument clone() {
        try {
            WordDocument wordDocument = (WordDocument) super.clone();
            wordDocument.text = this.text;
            wordDocument.mImages = (ArrayList<String>) this.mImages.clone();
            return wordDocument;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

打印輸入結(jié)果:

--文檔內(nèi)容展示 begin--
Text :bob
String :1
--文檔內(nèi)容展示 end--
--文檔復(fù)制內(nèi)容展示 begin--
Text :bob1
String :1
String :44
--文檔復(fù)制內(nèi)容展示 end--
--文檔內(nèi)容重新展示 begin--
Text :bob
String :1
--文檔內(nèi)容重新展示 end--

原型模式是比較簡(jiǎn)單的一個(gè)模式,它的核心問(wèn)題就是對(duì)原始對(duì)象進(jìn)行拷貝,為了減少錯(cuò)誤,建議每次都進(jìn)行深拷貝。

4.原型設(shè)計(jì)模式在Android源碼中的應(yīng)用

5.原型設(shè)計(jì)模式總結(jié)

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

在內(nèi)存中二進(jìn)制流進(jìn)行拷貝,要比直接new 一個(gè)對(duì)象性能要好。

  1. 如果創(chuàng)建新的對(duì)象比較復(fù)雜時(shí),可以利用原型模式簡(jiǎn)化對(duì)象的創(chuàng)建過(guò)程,同時(shí)也能提高效率
  2. 可以使用深拷貝保持原始對(duì)象的狀態(tài)
  3. 原型模式提供了簡(jiǎn)化的創(chuàng)建結(jié)構(gòu)

5.2缺點(diǎn)

直接在內(nèi)存中進(jìn)行拷貝,是不會(huì)執(zhí)行構(gòu)造函數(shù)的,減少了約束。優(yōu)點(diǎn)是減少了約束,缺點(diǎn)也是減少了約束。

  1. 在實(shí)現(xiàn)深拷貝的時(shí)候可能需要比較復(fù)雜的代碼
  2. 需要為每一個(gè)類配備一個(gè)clone 方法,而且這個(gè)clone 方法需要對(duì)類的整體功能進(jìn)行考慮,這對(duì)全新的類來(lái)說(shuō)并不困難,但對(duì)已有的類進(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ù)。

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