成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

一起學(xué)設(shè)計(jì)模式 - 原型模式

DevTalking / 3319人閱讀

摘要:原型模式是創(chuàng)建模式的一種,其作用是提高創(chuàng)建效率,減少計(jì)算機(jī)資源開(kāi)銷(xiāo),與工廠模式類(lèi)似的是,都屏蔽了對(duì)象實(shí)例化的過(guò)程概述原型模式是模式的一種,其特點(diǎn)就是通過(guò)克隆拷貝的方式來(lái),節(jié)約創(chuàng)建成本和資源,被拷貝的對(duì)象模型就稱(chēng)之為原型。

原型模式(Prototype Pattern)是創(chuàng)建模式的一種,其作用是提高創(chuàng)建效率,減少計(jì)算機(jī)資源開(kāi)銷(xiāo),與工廠模式類(lèi)似的是,都屏蔽了對(duì)象實(shí)例化的過(guò)程...

概述

原型模式23GOF模式的一種,其特點(diǎn)就是通過(guò)克隆/拷貝的方式來(lái),節(jié)約創(chuàng)建成本和資源,被拷貝的對(duì)象模型就稱(chēng)之為原型

舉例:在寫(xiě)PPT的時(shí)候,大多情況下模板風(fēng)格都是一致的,只是其中部分描述內(nèi)容發(fā)生變化,這個(gè)時(shí)候你會(huì)選擇Ctrl+C/V還是新建一頁(yè)PPT一邊聽(tīng)《從頭再來(lái)》一邊調(diào)整圖片和樣式?

JAVA中對(duì)原型模式提供了良好的支持,我們只需要實(shí)現(xiàn)Cloneable接口即可,它的目的就是將對(duì)象標(biāo)記為可被復(fù)制

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

簡(jiǎn)化對(duì)象創(chuàng)建過(guò)程,通過(guò)拷貝的方式構(gòu)建效率更高

可運(yùn)行時(shí)指定動(dòng)態(tài)創(chuàng)建的對(duì)象

缺點(diǎn)

需要實(shí)現(xiàn) Cloneable接口,clone位于內(nèi)部,不易擴(kuò)展,容易違背開(kāi)閉原則(程序擴(kuò)展,不應(yīng)該修改原有代碼)

默認(rèn)的 clone 只是淺克隆,深度克隆需要額外編碼(比如:統(tǒng)一實(shí)現(xiàn)Cloneable接口,或者序列化方式,還有org.apache.commons:commons-lang3.SerializationUtils.java)

注意點(diǎn)

通過(guò)內(nèi)存拷貝的方式構(gòu)建出來(lái)的,會(huì)忽略構(gòu)造函數(shù)限制

需要注意深拷貝淺拷貝,默認(rèn)Cloneable淺拷貝,只拷貝當(dāng)前對(duì)象而不會(huì)拷貝引用對(duì)象,除非自己實(shí)現(xiàn)深拷貝

單例模式沖突,clone是直接通過(guò)內(nèi)存拷貝的方式,繞過(guò)構(gòu)造方法

常用克隆不可變對(duì)象,如果你克隆的對(duì)象10個(gè)字段改9個(gè)還不如實(shí)例化算了

clone只是一個(gè)語(yǔ)法,非強(qiáng)制方法命名

很少多帶帶出現(xiàn),常與工廠模式相伴

適用場(chǎng)景

常用在初始化步驟繁瑣,資源耗損嚴(yán)重的對(duì)象

案例

案例一:淺拷貝

class Address {
    private String description;
    // 省略 Getter And Setter 
}
public class Customer implements Cloneable {

    private int id;
    private String name;
    private Address address;
    private List hobbies;

    // 省略 Getter And Setter 

    @Override
    protected Customer clone() throws CloneNotSupportedException {
        return (Customer) super.clone();
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name="" + name + """ +
                ", address=" + address +
                ", hobbies=" + hobbies +
                ",  customer-hashCode=" + this.hashCode() +
                ",  address-hashCode=" + this.address.hashCode() +
                "}";
    }
}

public class PrototypeDemo {

    public static void main(String[] args) throws CloneNotSupportedException {
        List hobbies = new ArrayList<>();
        hobbies.add("籃球");
        hobbies.add("足球");
        Customer original = new Customer(1, "淘寶客戶(hù)-1", new Address("上海市"), hobbies);
        Customer cloned = original.clone();
        System.out.println("http:////////////////////////////////////////////////// 修改前原始信息信息 - 開(kāi)始 //////////////////////////////////////////////////");
        System.out.println("原始信息:" + original.toString());
        System.out.println("拷貝信息:" + cloned.toString());
        System.out.println("http:////////////////////////////////////////////////// 修改前原始信息信息 - 結(jié)束 //////////////////////////////////////////////////

");
    }
}

分析: 從日志中可以發(fā)現(xiàn),我們無(wú)需通過(guò)new Object()的方式去實(shí)例化對(duì)象,而是調(diào)用Object.clone()同樣可以,CustomerhashCode也發(fā)生了改變,由此可以推斷出它們的引用已經(jīng)發(fā)生變化了,但是AddresshashCode一模一樣,前面說(shuō)到過(guò)Cloneable淺克隆的,并不會(huì)拷貝其它引用對(duì)象

////////////////////////////////////////////////// 修改前原始信息信息 - 開(kāi)始 //////////////////////////////////////////////////
原始信息:Customer{id=1, name="淘寶客戶(hù)-1", address=Address{description="上海市"}, hobbies=[籃球, 足球],  customer-hashCode=460141958,  address-hashCode=1163157884}
拷貝信息:Customer{id=1, name="淘寶客戶(hù)-1", address=Address{description="上海市"}, hobbies=[籃球, 足球],  customer-hashCode=1956725890,  address-hashCode=1163157884}
////////////////////////////////////////////////// 修改前原始信息信息 - 結(jié)束 //////////////////////////////////////////////////

案例二:淺拷貝

public class PrototypeDemo {

    public static void main(String[] args) throws CloneNotSupportedException {
        List hobbies = new ArrayList<>();
        hobbies.add("籃球");
        hobbies.add("足球");
        Customer original = new Customer(1, "淘寶客戶(hù)-1", new Address("上海市"), hobbies);
        Customer cloned = original.clone();

        System.out.println("http:////////////////////////////////////////////////// 修改后原始信息信息 - 開(kāi)始 //////////////////////////////////////////////////");
        original.setName("淘寶客戶(hù)-2");
        original.getHobbies().add("音樂(lè)");
        System.out.println("原始信息:" + original.toString());
        System.out.println("拷貝信息:" + cloned.toString());
        System.out.println("http:////////////////////////////////////////////////// 修改后原始信息信息 - 結(jié)束 //////////////////////////////////////////////////

");
    }
}

分析: Customer本身的屬性值修改與原始對(duì)象并不沖突,它們都是各自一份,但集合類(lèi)型修改后,克隆對(duì)象輸出的與原始對(duì)象如出一轍,不難發(fā)現(xiàn)Cloneable淺克隆范圍只支持基本類(lèi)型

////////////////////////////////////////////////// 修改后原始信息信息 - 開(kāi)始 //////////////////////////////////////////////////
原始信息:Customer{id=1, name="淘寶客戶(hù)-2", address=Address{description="上海市"}, hobbies=[籃球, 足球, 音樂(lè)],  customer-hashCode=460141958,  address-hashCode=1163157884}
拷貝信息:Customer{id=1, name="淘寶客戶(hù)-1", address=Address{description="上海市"}, hobbies=[籃球, 足球, 音樂(lè)],  customer-hashCode=1956725890,  address-hashCode=1163157884}
////////////////////////////////////////////////// 修改后原始信息信息 - 結(jié)束 //////////////////////////////////////////////////

案例三:深淺拷貝命名?

class Address implements Cloneable {
    // Address 也實(shí)現(xiàn) Cloneable
}

@Override
protected Address clone() throws CloneNotSupportedException {
    return (Address) super.clone();
}


public class Customer implements Cloneable {

    // 重復(fù)代碼省略...

    protected Customer shallow() throws CloneNotSupportedException {
        return (Customer) super.clone();
    }

    protected Customer deep() throws CloneNotSupportedException {
        Customer clone = (Customer) super.clone();
        clone.setAddress(clone.getAddress().clone());
        return clone;
    }
}

public class PrototypeDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        System.out.println("http:////////////////////////////////////////////////// 半深淺克隆 - 開(kāi)始 //////////////////////////////////////////////////");
        original.setAddress(new Address("北京市"));
        Customer shallow = original.shallow();
        System.out.println("淺克?。? + shallow.toString());

        Customer deep = original.deep();
        original.setAddress(new Address("天津市"));
        original.getHobbies().add("電影");
        System.out.println("深克?。? + deep.toString());
        System.out.println("http:////////////////////////////////////////////////// 半深淺克隆 - 結(jié)束 //////////////////////////////////////////////////

");
    }
}

分析: 我們定義了兩個(gè)非clone的方法名,同樣可以做到克隆特性,此時(shí)從deep()中可以看到修改原始的Address并沒(méi)有影響到現(xiàn)有的克隆對(duì)象,這是因?yàn)閮?nèi)部通過(guò)硬編碼的方式控制的,雖然引用的Address對(duì)象發(fā)生改變,但是List還是同一個(gè)引用,依舊做不到完全的深度克隆

////////////////////////////////////////////////// 半深淺克隆 - 開(kāi)始 //////////////////////////////////////////////////
淺克隆:Customer{id=1, name="淘寶客戶(hù)-2", address=Address{description="北京市"}, hobbies=[籃球, 足球, 音樂(lè)],  customer-hashCode=356573597,  address-hashCode=1735600054}
深克?。篊ustomer{id=1, name="淘寶客戶(hù)-2", address=Address{description="北京市"}, hobbies=[籃球, 足球, 音樂(lè), 電影],  customer-hashCode=21685669,  address-hashCode=2133927002}
////////////////////////////////////////////////// 半深淺克隆 - 結(jié)束 //////////////////////////////////////////////////

案例四:序列化實(shí)現(xiàn)深度克隆

class Address implements Cloneable,Serializable {

    private static final long serialVersionUID = 783202091017893997L;

}
public class Customer implements Cloneable, Serializable {
    private static final long serialVersionUID = 783202091017893997L;

    protected Customer deepCopy() throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(this);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        return (Customer) in.readObject();
    }
}

public class PrototypeDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        System.out.println("http:////////////////////////////////////////////////// 深淺克隆 - 開(kāi)始 //////////////////////////////////////////////////");
        Customer deepCopy = original.deepCopy();
        original.setAddress(new Address("長(zhǎng)沙市"));
        original.getHobbies().add("乒乓球");
        System.out.println("深克?。? + deepCopy.toString());

        System.out.println("http:////////////////////////////////////////////////// 深淺克隆 - 結(jié)束 //////////////////////////////////////////////////

");
    }
}

分析: 實(shí)現(xiàn)Serializable,通過(guò)序列化的方式與原始數(shù)據(jù)完全脫離關(guān)系,從而達(dá)到深度克隆效果,當(dāng)然一般用SerializationUtils.clone(original)方式比我們自己寫(xiě)的會(huì)更好


    org.apache.commons
    commons-lang3
    3.4
////////////////////////////////////////////////// 深淺克隆 - 開(kāi)始 //////////////////////////////////////////////////
深克?。篊ustomer{id=1, name="淘寶客戶(hù)-2", address=Address{description="天津市"}, hobbies=[籃球, 足球, 音樂(lè), 電影],  customer-hashCode=1020371697,  address-hashCode=789451787}
////////////////////////////////////////////////// 深淺克隆 - 結(jié)束 //////////////////////////////////////////////////

案例五:如何配合工廠模式使用?

這個(gè)簡(jiǎn)單問(wèn)題就留給讀者思考吧,歡迎探討交流,三人行必有我?guī)?!!
總結(jié)

本章介紹了什么是原型模式以及使用它的優(yōu)缺點(diǎn),其模式在開(kāi)發(fā)過(guò)程中幾乎用不上(反正我沒(méi)用到過(guò),歡迎探討),但這并不能說(shuō)明它是無(wú)用,存在即合理,設(shè)計(jì)模式不僅用作與JAVA軟件編程,更多情況下模式的作用是在某種程度下避免復(fù)雜的設(shè)計(jì)

- 說(shuō)點(diǎn)什么

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter3/battcn-prototype

個(gè)人QQ:1837307557

battcn開(kāi)源群(適合新手):391619659

微信公眾號(hào):battcn(歡迎調(diào)戲)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67912.html

相關(guān)文章

  • 互聯(lián)網(wǎng)常用設(shè)計(jì)模式——通往架構(gòu)師的第一步

    摘要:設(shè)計(jì)模式的分類(lèi)經(jīng)典應(yīng)用框架中常見(jiàn)的設(shè)計(jì)模式分為三類(lèi)創(chuàng)建型模式對(duì)類(lèi)的實(shí)例化過(guò)程的抽象。對(duì)象的結(jié)構(gòu)模式是動(dòng)態(tài)的。對(duì)象的行為模式則使用對(duì)象的聚合來(lái)分配行為。設(shè)計(jì)模式是個(gè)好東西,以后肯定還要進(jìn)一步的學(xué)習(xí),并且在項(xiàng)目中多實(shí)踐,提升自己的設(shè)計(jì)能力。 什么是設(shè)計(jì)模式? Christopher Alexander?說(shuō)過(guò):每一個(gè)模式描述了一個(gè)在我們周?chē)粩嘀貜?fù)發(fā)生的問(wèn)題,以及該問(wèn)題的解決方案的核心。這樣...

    張紅新 評(píng)論0 收藏0
  • Javascript學(xué)習(xí)之創(chuàng)建對(duì)象

    摘要:在中,除了幾種原始類(lèi)型外,其余皆為對(duì)象,,既然對(duì)象如此重要,那就列舉一下在中如何創(chuàng)建對(duì)象通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象實(shí)例對(duì)象字面量對(duì)象字面量是對(duì)象定義的一種簡(jiǎn)寫(xiě)形式,目的在于簡(jiǎn)化創(chuàng)建包含大量屬性的對(duì)象的過(guò)程。 在Javascript中,除了幾種原始類(lèi)型外,其余皆為對(duì)象(Object,Array ...),既然對(duì)象如此重要,那就列舉一下在Javascript中如何創(chuàng)建對(duì)象: 通過(guò)Object構(gòu)造...

    jollywing 評(píng)論0 收藏0
  • 和少婦白潔一起學(xué)JavaScript

    摘要:我們已經(jīng)回答了的構(gòu)造函數(shù)和原型都是誰(shuí)的問(wèn)題,現(xiàn)在牽扯出來(lái)一個(gè),我們繼續(xù)檢查的構(gòu)造函數(shù)是全局對(duì)象上屬性叫的對(duì)象的原型是個(gè)匿名函數(shù),按照關(guān)于構(gòu)造函數(shù)的約定,它應(yīng)該是構(gòu)造函數(shù)的屬性我們給這個(gè)對(duì)象起個(gè)名字,叫。 我不確定JavaScript語(yǔ)言是否應(yīng)該被稱(chēng)為Object-Oriented,因?yàn)镺bject Oriented是一組語(yǔ)言特性、編程模式、和設(shè)計(jì)與工程方法的籠統(tǒng)稱(chēng)謂,沒(méi)有一個(gè)詳盡和大家...

    DevTTL 評(píng)論0 收藏0
  • H5學(xué)習(xí)

    摘要:為此決定自研一個(gè)富文本編輯器。本文,主要介紹如何實(shí)現(xiàn)富文本編輯器,和解決一些不同瀏覽器和設(shè)備之間的。 對(duì)ES6Generator函數(shù)的理解 Generator 函數(shù)是 ES6 提供的一種異步編程解決方案,語(yǔ)法行為與傳統(tǒng)函數(shù)完全不同。 JavaScript 設(shè)計(jì)模式 ② 巧用工廠模式和創(chuàng)建者模式 我為什么把他們兩個(gè)放在一起講?我覺(jué)得這兩個(gè)設(shè)計(jì)模式有相似之處,有時(shí)候會(huì)一個(gè)設(shè)計(jì)模式不能滿...

    aristark 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

DevTalking

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<