最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java設(shè)計(jì)模式之單例和原型

 更新時(shí)間:2022年10月11日 09:06:27   作者:tianClassmate  
這篇文章介紹了Java設(shè)計(jì)模式之單例和原型,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

今天這篇文章我們來(lái)學(xué)習(xí)創(chuàng)建型設(shè)計(jì)模式的另外兩個(gè)孿生兄弟,單例和原型,其中原型設(shè)計(jì)模式中我們深入到JVM的內(nèi)存模型,最后順便談?wù)凧ava中的值傳遞和引用傳遞。

上篇文章老王買產(chǎn)品 我們從最原始的基本實(shí)現(xiàn)方法,到簡(jiǎn)單(靜態(tài))工廠,然后使用工廠方法設(shè)計(jì)模式進(jìn)行改造,最后考慮產(chǎn)品會(huì)產(chǎn)生變體,我們又?jǐn)U展到了抽象工廠。

設(shè)計(jì)模式所有的相關(guān)代碼均已上傳到碼云 讀者可以自行下載學(xué)習(xí)測(cè)試,本地源碼下載。

一、引出問(wèn)題

今天老王又來(lái)了,還是想買我們的產(chǎn)品,今天老王上老就提出來(lái)一個(gè)要求,當(dāng)他購(gòu)買產(chǎn)品的時(shí)候,每次都要從貨架上給他拿相同的一個(gè)。

如果用傳統(tǒng)實(shí)現(xiàn)方式,當(dāng)老王拿到產(chǎn)品以后,直接和上一個(gè)比對(duì)一下就行了,如果不一致老王就還回來(lái)。

但通過(guò)我們查閱軟件的七大設(shè)計(jì)原則 ,這很明顯違反了依賴倒置原則,為了避免耦合和讓代碼更易于維護(hù),老王是不能依賴具體產(chǎn)品的。

二、單例

我們就需要將產(chǎn)品比對(duì)在創(chuàng)建產(chǎn)品的時(shí)候進(jìn)行判斷,老王就只管拿。

老王來(lái)之前應(yīng)該還有兩種情況,一種就是老王還沒(méi)來(lái),產(chǎn)品就準(zhǔn)備好了,也即餓漢式。第二種就是老王什么時(shí)候來(lái),什么時(shí)候給他準(zhǔn)備產(chǎn)品,也即懶漢式。

我們看具體的實(shí)現(xiàn)代碼:

懶漢式:

/**
 * 懶漢式
 * @author tcy
 * @Date 29-07-2022
 */
public class LazySingletonProduct {

    private static volatile LazySingletonProduct instance=null;

    private LazySingletonProduct(){}

    public static synchronized LazySingletonProduct getInstance(){
        if (instance==null){
            instance=new LazySingletonProduct();

        }
        return instance;
    }

餓漢式:

/**
 * 餓漢式
 * @author tcy
 * @Date 29-07-2022
 */
public class HungrySingletonProduct {
    private static volatile HungrySingletonProduct instance=new HungrySingletonProduct();

    private HungrySingletonProduct(){};

    public static synchronized HungrySingletonProduct getInstance(){
        if (instance==null){
            instance=new HungrySingletonProduct();
        }
        return instance;
    }
}

老王類:

/**
 * @author tcy
 * @Date 29-07-2022
 */
public class Client {
    public static void main(String[] args) {
        HungrySingletonProduct instance1 = HungrySingletonProduct.getInstance();
        HungrySingletonProduct instance2 = HungrySingletonProduct.getInstance();

        if (instance1==instance2){
            System.out.println("我倆一樣...");
        }else {
            System.out.println("我倆不一樣...");
        }
    }
}

以上就是單例設(shè)計(jì)模式中的懶漢式和餓漢式,應(yīng)該是設(shè)計(jì)模式中最簡(jiǎn)單的一個(gè),理解起來(lái)難度也不大。

為了克服老王和他兒子小王一起來(lái)拿錯(cuò)的尷尬,我們?cè)诜椒ㄉ霞觭ynchronized鎖,對(duì)象引用上加volatile共享變量,但這樣會(huì)帶來(lái)效率問(wèn)題,如果不考慮多線程需求,讀者可自行去掉。

三、原型

老王今天很明顯是找茬,他繼續(xù)說(shuō),如果我不想要一個(gè)了,我要每次買都要不同的,你看著辦。

每次創(chuàng)建產(chǎn)品都要不同的,傳統(tǒng)的方式肯定就是重新new一個(gè)對(duì)象,但每創(chuàng)建一個(gè)對(duì)象都是一個(gè)復(fù)雜的過(guò)程,而且這樣還會(huì)帶來(lái)一定的代碼冗余。

這就需要用到創(chuàng)建型設(shè)計(jì)模式中的原型模式中的拷貝,其中又分為淺拷貝和深拷貝。

我們先看基本概念。

  • 淺克?。簞?chuàng)建一個(gè)新對(duì)象,對(duì)象種屬性和原來(lái)對(duì)象的屬性完全相同,對(duì)于非基本類型屬性仍指向原有屬性所指向的內(nèi)存地址
  • 深克?。簞?chuàng)建一個(gè)新對(duì)象,屬性中引用類型也會(huì)被克隆,不再指向原來(lái)屬性所指向的內(nèi)存地址

這段意思也就是,老王購(gòu)買產(chǎn)品的時(shí)候,如果產(chǎn)品都是基本數(shù)據(jù)類型(byte(位)、short(短整數(shù))、int(整數(shù))、long(長(zhǎng)整數(shù))、float(單精度)、double(雙精度)、char(字符)和boolean(布爾值))和String,那么我們就使用淺拷貝。

如果產(chǎn)品包括別的產(chǎn)品(對(duì)象)的引用類型就要使用深拷貝。

如果想搞明白,為什么造成深拷貝和淺拷貝這個(gè)問(wèn)題,我們就要重點(diǎn)說(shuō)說(shuō)JVM的內(nèi)存模型。

我們聲明一個(gè)基本數(shù)據(jù)類型的變量a=2,實(shí)際上是在棧中直接存儲(chǔ)了一個(gè)a=2,當(dāng)拷貝的時(shí)候直接把值拷貝過(guò)去,也就是直接有了一份a的副本。

當(dāng)我們創(chuàng)建一個(gè)對(duì)象時(shí)Student stu=new Student(),實(shí)際上對(duì)象的值存儲(chǔ)在堆中,在棧中只存放了stu="對(duì)象地址",stu指向了堆中的地址,jvm拷貝的時(shí)候只復(fù)制了棧中的地址,實(shí)際上他們堆中的對(duì)象還是一個(gè)。

我們?cè)賮?lái)看String類型。String 存在于堆內(nèi)存、常量池;這種比較特殊, 傳遞是引用地址;由本身的final性, 每次賦值都是一個(gè)新的引用地址,原對(duì)象的引用和副本的引用互不影響。因此String就和基本數(shù)據(jù)類型一樣,表現(xiàn)出了"深拷貝"特性。

我們具體看實(shí)現(xiàn)代碼:

淺拷貝類:

/**
 * @author tcy
 * @Date 29-07-2022
 */
public class ShallowProduct implements Cloneable{

    private String name;

    private int num;

    public void show(){
        System.out.println("這是淺產(chǎn)品..."+name+"數(shù)量:"+num);
    }

    public String getName() {
        return name;
    }

    public ShallowProduct setName(String name) {
        this.name = name;
        return this;
    }

    public int getNum() {
        return num;
    }

    public ShallowProduct setNum(int num) {
        this.num = num;
        return this;
    }

    @Override
    public ShallowProduct clone() throws CloneNotSupportedException {
        return (ShallowProduct) super.clone();
    }
}

如果需要哪個(gè)對(duì)象淺拷貝,需要該對(duì)象實(shí)現(xiàn)Cloneable接口,并重寫clone()方法。

public void shallowTest()throws CloneNotSupportedException{
    ShallowProduct product1=new ShallowProduct();
    ShallowProduct product2 = product1.clone();
    product1.setName("老王");
    product2.setName("老李");

    product1.setNum(1);
    product2.setNum(2);

    product1.show();

    product2.show();
}

調(diào)用時(shí)輸出的對(duì)象中的值直接就是兩個(gè)不同的對(duì)象,實(shí)現(xiàn)了對(duì)象的淺拷貝。

如果該對(duì)象中包括引用類型呢?那怎么實(shí)現(xiàn)呢。

其實(shí)原理上也是很簡(jiǎn)單的,只需要將非基本數(shù)據(jù)類型也像淺拷貝那樣操做就行了,然后在當(dāng)前clone()方法中,調(diào)用非基本數(shù)據(jù)類型的clone()方法

深拷貝引用類:

/**
 * @author tcy
 * @Date 29-07-2022
 */
public class Child implements Cloneable{

    private String childName;

    public String getChildName() {
        return childName;
    }

    public Child setChildName(String childName) {
        this.childName = childName;
        return this;
    }

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

深拷貝類:

/**
 * @author tcy
 * @Date 29-07-2022
 */
public class DeepProduct implements Cloneable{

    private String name;

    private Integer num;

    private Child child;
    public String getName() {
        return name;
    }

    public DeepProduct setName(String name) {
        this.name = name;
        return this;
    }

    public Integer getNum() {
        return num;
    }

    public DeepProduct setNum(Integer num) {
        this.num = num;
        return this;
    }

    public void show(){
        System.out.println("這是深產(chǎn)品..."+name+"數(shù)量:"+num+"包括child:"+child.getChildName());
    }


    @Override
    public DeepProduct clone() throws CloneNotSupportedException {
        DeepProduct clone = (DeepProduct) super.clone();
        clone.child=child.clone();
        return clone;
    }

    public Child getChild() {
        return child;
    }

    public DeepProduct setChild(Child child) {
        this.child = child;
        return this;
    }
}

我們測(cè)試一下對(duì)象中的值是否發(fā)生了改變。

public void deepTest() throws CloneNotSupportedException {
    DeepProduct product1=new DeepProduct();
    Child child=new Child();
    child.setChildName("老王child");

    product1.setName("老王");
    product1.setNum(1);
    product1.setChild(child);

    //--------------
    DeepProduct product2=product1.clone();
    product2.setName("老李");
    product2.setNum(2);
    product2.getChild().setChildName("老李child");

    product1.show();
    product2.show();
}

老李、老王都正確的輸出了,說(shuō)明實(shí)現(xiàn)沒(méi)有問(wèn)題。

這樣就符合了老王的要求。

既然說(shuō)到了jvm的內(nèi)存模型,就有必要說(shuō)一下java中的值傳遞和引用傳遞。

實(shí)際上java應(yīng)該就是值傳遞,在調(diào)用方法的時(shí)候,如果參數(shù)是基本數(shù)據(jù)類型,那么傳遞的就是副本,我們?cè)诜椒ㄖ袩o(wú)論怎么給他賦值,他原本的值都不會(huì)有變化。

在調(diào)用方法的時(shí)候,如果參數(shù)是引用數(shù)據(jù)類型,那么傳遞的就是這個(gè)對(duì)象的地址,我們?cè)诜椒ㄖ行薷倪@個(gè)對(duì)象都會(huì)影響他原本的對(duì)象。

造成這個(gè)現(xiàn)象的原因其實(shí)是和淺拷貝、深拷貝的原理是一樣的,都是棧、堆內(nèi)存的結(jié)構(gòu)導(dǎo)致的。

老王看他的要求都滿足了,最后心滿意足的拿著產(chǎn)品走了。

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

  • Spring-Boot 集成Solr客戶端的詳細(xì)步驟

    Spring-Boot 集成Solr客戶端的詳細(xì)步驟

    本篇文章主要介紹了Spring-Boot 集成Solr客戶端的詳細(xì)步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • JavaWeb入門:HttpResponse和HttpRequest詳解

    JavaWeb入門:HttpResponse和HttpRequest詳解

    這篇文章主要介紹了Django的HttpRequest和HttpResponse對(duì)象,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • 關(guān)于@EnableGlobalMethodSecurity注解的用法解讀

    關(guān)于@EnableGlobalMethodSecurity注解的用法解讀

    這篇文章主要介紹了關(guān)于@EnableGlobalMethodSecurity注解的用法解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Go Java算法之從英文中重建數(shù)字示例詳解

    Go Java算法之從英文中重建數(shù)字示例詳解

    這篇文章主要為大家介紹了Go Java算法之從英文中重建數(shù)字示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Java文件處理之使用XWPFDocument導(dǎo)出Word文檔

    Java文件處理之使用XWPFDocument導(dǎo)出Word文檔

    最近因項(xiàng)目開(kāi)發(fā)的需要,整理了一份用JAVA導(dǎo)出WORD文檔,下面這篇文章主要給大家介紹了關(guān)于Java文件處理之使用XWPFDocument導(dǎo)出Word文檔的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • 新版SpringSecurity5.x使用與配置詳解

    新版SpringSecurity5.x使用與配置詳解

    Spring Security是一個(gè)強(qiáng)大且高度可定制的身份驗(yàn)證和訪問(wèn)控制框架,本文主要介紹了新版SpringSecurity5.x使用與配置詳解,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之平行志愿管理系統(tǒng)的實(shí)現(xiàn)

    Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之平行志愿管理系統(tǒng)的實(shí)現(xiàn)

    這是一個(gè)使用了java+Springboot+Maven+mybatis+Vue+Mysql開(kāi)發(fā)的圖片平行志愿管理系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有志愿管理該有的所有功能,感興趣的朋友快來(lái)看看吧
    2022-02-02
  • 使用SpringBoot的CommandLineRunner遇到的坑及解決

    使用SpringBoot的CommandLineRunner遇到的坑及解決

    這篇文章主要介紹了使用SpringBoot的CommandLineRunner遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • MyBatis中調(diào)用存儲(chǔ)過(guò)程和函數(shù)的實(shí)現(xiàn)示例

    MyBatis中調(diào)用存儲(chǔ)過(guò)程和函數(shù)的實(shí)現(xiàn)示例

    在MyBatis中調(diào)用存儲(chǔ)過(guò)程和函數(shù)是一個(gè)相對(duì)高級(jí)的特性,本文主要介紹了MyBatis中調(diào)用存儲(chǔ)過(guò)程和函數(shù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • 詳解Mybatis(五)Mapper接口

    詳解Mybatis(五)Mapper接口

    這篇文章主要介紹了Mybatis Mapper接口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評(píng)論

香港| 蓬安县| 河南省| 沐川县| 木里| 神木县| 依安县| 乐安县| 陇南市| 武夷山市| 西贡区| 华安县| 崇礼县| 翁源县| 寿光市| 武山县| 无锡市| 汤阴县| 汽车| 行唐县| 安化县| 军事| 磐安县| 景宁| 黄石市| 通江县| 乌兰县| 巧家县| 安丘市| 孝昌县| 丰都县| 蓝田县| 扎赉特旗| 乌苏市| 迁安市| 凤翔县| 方正县| 礼泉县| 淄博市| 东乌珠穆沁旗| 昭觉县|