三院尔、設(shè)計(jì)模式之原型模式

定義:用原型實(shí)例指定創(chuàng)建實(shí)例的種類,并通過拷貝這些原型創(chuàng)建新的對(duì)象喉誊;

使用場(chǎng)景:

  • 類初始化需要消化非常多的資源,這個(gè)資源包括數(shù)據(jù)纵顾、硬件資源等伍茄,通過原型拷貝避免這些消耗侧但;
  • 通過 new 產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備和訪問權(quán)限時(shí)府瞄;
  • 一個(gè)對(duì)象需要提供給其他對(duì)象訪問邦鲫,而且各個(gè)調(diào)用者可能都需要修改其值時(shí)低矮,可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者使用,即保護(hù)性拷貝曹仗;

注意:通過實(shí)現(xiàn)Cloneable接口的原型模式在調(diào)用clone函數(shù)構(gòu)造實(shí)例時(shí)并不一定比通過new的操作速度快榨汤,只有當(dāng)通過new構(gòu)造對(duì)象較為耗時(shí)或者說(shuō)成本較高時(shí),通過clone方法才能獲得效率上的提升怎茫。實(shí)現(xiàn)原型模式也不一定需要實(shí)現(xiàn)Cloneable接口收壕,也有其他的實(shí)現(xiàn)方式。


簡(jiǎn)單實(shí)現(xiàn):
例:創(chuàng)建一個(gè)文檔對(duì)象為WordDocument轨蛤,這個(gè)文檔中含有文字和圖片蜜宪。用戶經(jīng)過長(zhǎng)時(shí)間的內(nèi)容編輯后,將其保存后并拷貝一個(gè)副本重新進(jìn)行編輯祥山;

/**
 * 文檔類型
 */
class WordDocument implements Cloneable {
    private String mText;
    private ArrayList<String> images = new ArrayList<>();

    public WordDocument() {
        System.out.println("執(zhí)行WordDocument的構(gòu)造函數(shù)");
    }

    public String getText() {
        return mText;
    }

    public void setText(String text) {
        mText = text;
    }

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

    public void addImage(String img) {
        this.images.add(img);
    }

    @Override
    public WordDocument clone() {
        try {
            WordDocument doc = (WordDocument) super.clone();
            doc.mText = this.mText;
            doc.images = this.images;
            return doc;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void showDocument() {
        System.out.println("———————打印WordDocument開始-----------");
        System.out.println("對(duì)象:" + super.toString());
        System.out.println("文本:" + mText);
        System.out.println("圖片集合:");
        for (String imageName : images) {
            System.out.println(imageName);
        }
        System.out.println("———————打印完成--------------------------");
    }
}

/**
 * Created by admin on 2019/2/22.
 * 原型模式
 */
public class Client {
    public static void main(String args[]){
        //1圃验、構(gòu)建文本對(duì)象
        WordDocument originDoc = new WordDocument();
        //2、編輯缝呕,添加文本和圖片
        originDoc.setText("這是一篇用來(lái)學(xué)習(xí)原型模式的文檔");
        originDoc.addImage("假圖片1");
        originDoc.addImage("假圖片2");
        originDoc.showDocument();
        //3澳窑、拷貝一份副本
        WordDocument doc2 = originDoc.clone();
        doc2.showDocument();
        //4、修改文檔副本
        doc2.setText("拷貝的文檔2");
        doc2.showDocument();

        originDoc.showDocument();
    }
}

運(yùn)行結(jié)果:

執(zhí)行WordDocument的構(gòu)造函數(shù)
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@4554617c
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@74a14482
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@74a14482
文本:拷貝的文檔2
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@4554617c
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------

從結(jié)果可以看出:使用clone()生成的對(duì)象doc2和第一個(gè)對(duì)象實(shí)例不同但內(nèi)容相同供常,且doc2是不會(huì)執(zhí)行構(gòu)造方法的摊聋,當(dāng)修改了doc2的內(nèi)容的內(nèi)容時(shí)并不會(huì)修改originDoc的內(nèi)容。

淺拷貝和深拷貝

上述原型模式的實(shí)現(xiàn)實(shí)際是一個(gè)淺拷貝话侧,這種拷貝實(shí)際上并不是將原始文檔的所有字段都重新構(gòu)造了一份栗精,而是副本文檔的字段引用原始文檔的字段;
我們知道A引用B就是說(shuō)兩個(gè)對(duì)象指向同一個(gè)地址瞻鹏,當(dāng)修改A時(shí)B也會(huì)改變悲立,B修改時(shí)A也會(huì)改變。上面的例子新博,將main函數(shù)修改為如下:

public static void main(String args[]){
        //1薪夕、構(gòu)建文本對(duì)象
        WordDocument originDoc = new WordDocument();
        //2、編輯赫悄,添加文本和圖片
        originDoc.setText("這是一篇用來(lái)學(xué)習(xí)原型模式的文檔");
        originDoc.addImage("假圖片1");
        originDoc.addImage("假圖片2");
        originDoc.showDocument();
        //3原献、拷貝一份副本
        WordDocument doc2 = originDoc.clone();
        doc2.showDocument();
        //4、修改文檔副本
        doc2.setText("拷貝的文檔2");
        doc2.addImage("doc2添加一張圖片");
        doc2.showDocument();

        originDoc.showDocument();
    }

查看結(jié)果:

執(zhí)行WordDocument的構(gòu)造函數(shù)
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@4554617c
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@74a14482
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@74a14482
文本:拷貝的文檔2
圖片集合:
假圖片1
假圖片2
doc2添加一張圖片
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@4554617c
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
doc2添加一張圖片
———————打印完成--------------------------

可以看到最后兩個(gè)對(duì)象打印結(jié)果是一樣的埂淮,都添加了一張圖片姑隅,這是由于clone方法中只是簡(jiǎn)單的進(jìn)行淺拷貝,引用類型的新對(duì)象doc2的images只是單純的指向了this.imags的引用倔撞,而沒有重新創(chuàng)建一個(gè)images對(duì)象讲仰,現(xiàn)在采用深拷貝解決上面顯示的問題,修改clone方法如下:

  @Override
    public WordDocument clone() {
        try {
            WordDocument doc = (WordDocument) super.clone();
            doc.mText = this.mText;
            doc.images = (ArrayList<String>) this.images.clone();
            return doc;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

運(yùn)行結(jié)果為:

執(zhí)行WordDocument的構(gòu)造函數(shù)
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@4554617c
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@74a14482
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@74a14482
文本:拷貝的文檔2
圖片集合:
假圖片1
假圖片2
doc2添加一張圖片
———————打印完成--------------------------
———————打印WordDocument開始-----------
對(duì)象:sl.com.designmodedemo.cloneabledesign.WordDocument@4554617c
文本:這是一篇用來(lái)學(xué)習(xí)原型模式的文檔
圖片集合:
假圖片1
假圖片2
———————打印完成--------------------------

可以看見痪蝇,現(xiàn)在再給Doc2副本添加圖片時(shí)鄙陡,就不會(huì)對(duì)原型對(duì)象進(jìn)行改變了冕房;


原型模式是非常簡(jiǎn)單的一個(gè)模式,它的核心問題就是對(duì)原始對(duì)象進(jìn)行拷貝趁矾,在這個(gè)模式的使用中需要注意一點(diǎn)的是:深耙册、淺拷貝的問題。在開發(fā)過程中毫捣,為了減少錯(cuò)誤详拙,使用時(shí)應(yīng)該盡量使用深拷貝,避免操作副本時(shí)影響原始對(duì)象的問題培漏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溪厘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子牌柄,更是在濱河造成了極大的恐慌畸悬,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件珊佣,死亡現(xiàn)場(chǎng)離奇詭異蹋宦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咒锻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門冷冗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人惑艇,你說(shuō)我怎么就攤上這事蒿辙。” “怎么了滨巴?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵思灌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我恭取,道長(zhǎng)泰偿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任蜈垮,我火速辦了婚禮耗跛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘攒发。我一直安慰自己调塌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布惠猿。 她就那樣靜靜地躺著羔砾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜒茄,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音餐屎,去河邊找鬼檀葛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛腹缩,可吹牛的內(nèi)容都是我干的屿聋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼藏鹊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼润讥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起盘寡,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤楚殿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后竿痰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脆粥,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年影涉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了变隔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蟹倾,死狀恐怖匣缘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鲜棠,我是刑警寧澤肌厨,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站岔留,受9級(jí)特大地震影響夏哭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜献联,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一竖配、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧里逆,春花似錦进胯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春盯漂,著一層夾襖步出監(jiān)牢的瞬間颇玷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工就缆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帖渠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓竭宰,卻偏偏與公主長(zhǎng)得像空郊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子切揭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容