亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java設計模式之單例和原型實例分析

發布時間:2022-09-26 09:56:53 來源:億速云 閱讀:113 作者:iii 欄目:開發技術

今天小編給大家分享一下Java設計模式之單例和原型實例分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

一、引出問題

今天老王又來了,還是想買我們的產品,今天老王上老就提出來一個要求,當他購買產品的時候,每次都要從貨架上給他拿相同的一個。

如果用傳統實現方式,當老王拿到產品以后,直接和上一個比對一下就行了,如果不一致老王就還回來。

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

二、單例

我們就需要將產品比對在創建產品的時候進行判斷,老王就只管拿。

老王來之前應該還有兩種情況,一種就是老王還沒來,產品就準備好了,也即餓漢式。第二種就是老王什么時候來,什么時候給他準備產品,也即懶漢式。

我們看具體的實現代碼:

懶漢式:

/**
 * 懶漢式
 * @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("我倆不一樣...");
        }
    }
}

以上就是單例設計模式中的懶漢式和餓漢式,應該是設計模式中最簡單的一個,理解起來難度也不大。

為了克服老王和他兒子小王一起來拿錯的尷尬,我們在方法上加synchronized鎖,對象引用上加volatile共享變量,但這樣會帶來效率問題,如果不考慮多線程需求,讀者可自行去掉。

三、原型

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

每次創建產品都要不同的,傳統的方式肯定就是重新new一個對象,但每創建一個對象都是一個復雜的過程,而且這樣還會帶來一定的代碼冗余。

這就需要用到創建型設計模式中的原型模式中的拷貝,其中又分為淺拷貝和深拷貝。

我們先看基本概念。

  • 淺克隆:創建一個新對象,對象種屬性和原來對象的屬性完全相同,對于非基本類型屬性仍指向原有屬性所指向的內存地址

  • 深克隆:創建一個新對象,屬性中引用類型也會被克隆,不再指向原來屬性所指向的內存地址

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

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

如果想搞明白,為什么造成深拷貝和淺拷貝這個問題,我們就要重點說說JVM的內存模型。

我們聲明一個基本數據類型的變量a=2,實際上是在棧中直接存儲了一個a=2,當拷貝的時候直接把值拷貝過去,也就是直接有了一份a的副本。

當我們創建一個對象時Student stu=new Student(),實際上對象的值存儲在堆中,在棧中只存放了stu="對象地址",stu指向了堆中的地址,jvm拷貝的時候只復制了棧中的地址,實際上他們堆中的對象還是一個。

我們再來看String類型。String 存在于堆內存、常量池;這種比較特殊, 傳遞是引用地址;由本身的final性, 每次賦值都是一個新的引用地址,原對象的引用和副本的引用互不影響。因此String就和基本數據類型一樣,表現出了"深拷貝"特性。

我們具體看實現代碼:

淺拷貝類:

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

    private String name;

    private int num;

    public void show(){
        System.out.println("這是淺產品..."+name+"數量:"+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();
    }
}

如果需要哪個對象淺拷貝,需要該對象實現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();
}

調用時輸出的對象中的值直接就是兩個不同的對象,實現了對象的淺拷貝。

如果該對象中包括引用類型呢?那怎么實現呢。

其實原理上也是很簡單的,只需要將非基本數據類型也像淺拷貝那樣操做就行了,然后在當前clone()方法中,調用非基本數據類型的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("這是深產品..."+name+"數量:"+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;
    }
}

我們測試一下對象中的值是否發生了改變。

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();
}

老李、老王都正確的輸出了,說明實現沒有問題。

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

既然說到了jvm的內存模型,就有必要說一下java中的值傳遞和引用傳遞。

實際上java應該就是值傳遞,在調用方法的時候,如果參數是基本數據類型,那么傳遞的就是副本,我們在方法中無論怎么給他賦值,他原本的值都不會有變化。

在調用方法的時候,如果參數是引用數據類型,那么傳遞的就是這個對象的地址,我們在方法中修改這個對象都會影響他原本的對象。

造成這個現象的原因其實是和淺拷貝、深拷貝的原理是一樣的,都是棧、堆內存的結構導致的。

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

以上就是“Java設計模式之單例和原型實例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

瑞金市| 酒泉市| 乐陵市| 河西区| 沂水县| 六盘水市| 威宁| 荆门市| 彭泽县| 轮台县| 健康| 忻城县| 弥勒县| 万年县| 桓台县| 若羌县| 民县| 榕江县| 固安县| 从江县| 四会市| 拉孜县| 贡山| 文安县| 太原市| 喀喇沁旗| 安乡县| 儋州市| 乐至县| 林芝县| 沐川县| 靖边县| 定安县| 棋牌| 永仁县| 阳新县| 泰兴市| 班玛县| 台江县| 高淳县| 和平县|