亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JAVA設計模式---原型模式你了解嗎

 更新時間:2021年09月03日 10:19:52   作者:大忽悠愛忽悠  
這篇文章主要介紹了JAVA 原型模式的的相關資料,文中講解非常細致,實例幫助大家更好的理解和學習,感興趣的朋友可以了解下

介紹

原型模式(Prototype Pattern):使用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。原型模式是一種對象創(chuàng)建型模式。

原型模式的工作原理很簡單:將一個原型對象傳給那個要發(fā)動創(chuàng)建的對象,這個要發(fā)動創(chuàng)建的對象通過請求原型對象拷貝自己來實現(xiàn)創(chuàng)建過程。

原型模式是一種“另類”的創(chuàng)建型模式,創(chuàng)建克隆對象的工廠就是原型類自身,工廠方法由克隆方法來實現(xiàn)。

需要注意的是通過克隆方法所創(chuàng)建的對象是全新的對象,它們在內存中擁有新的地址,通常對克隆所產(chǎn)生的對象進行修改對原型對象不會造成任何影響,每一個克隆對象都是相互獨立的。通過不同的方式修改可以得到一系列相似但不完全相同的對象。

角色

  • Prototype(抽象原型類):它是聲明克隆方法的接口,是所有具體原型類的公共父類,可以是抽象類也可以是接口,甚至還可以是具體實現(xiàn)類。
  • ConcretePrototype(具體原型類):它實現(xiàn)在抽象原型類中聲明的克隆方法,在克隆方法中返回自己的一個克隆對象。
  • Client(客戶類):讓一個原型對象克隆自身從而創(chuàng)建一個新的對象,在客戶類中只需要直接實例化或通過工廠方法等方式創(chuàng)建一個原型對象,再通過調用該對象的克隆方法即可得到多個相同的對象。由于客戶類針對抽象原型類Prototype編程,因此用戶可以根據(jù)需要選擇具體原型類,系統(tǒng)具有較好的可擴展性,增加或更換具體原型類都很方便。

原型模式的核心在于如何實現(xiàn)克隆方法。

Java語言提供的clone()方法

學過Java語言的人都知道,所有的Java類都繼承自 java.lang.Object。事實上,Object 類提供一個 clone() 方法,可以將一個Java對象復制一份。因此在Java中可以直接使用 Object 提供的 clone() 方法來實現(xiàn)對象的克隆,Java語言中的原型模式實現(xiàn)很簡單。

需要注意的是能夠實現(xiàn)克隆的Java類必須實現(xiàn)一個 標識接口 Cloneable,表示這個Java類支持被復制。如果一個類沒有實現(xiàn)這個接口但是調用了clone()方法,Java編譯器將拋出一個 CloneNotSupportedException 異常。

代碼演示—克隆羊

具體原型類:

//實現(xiàn)Cloneable接口
@Data
public class Sheep implements Cloneable
{
    private String name;
    private Integer age;
    //重寫Object的clone方法
    @Override
    protected Object clone() throws CloneNotSupportedException 
    {
        Sheep sheep=null;
        sheep=(Sheep)super.clone();
        return sheep;
    }
}

客戶端創(chuàng)建并克隆原型對象:

        //創(chuàng)建原型對象
        Sheep sheep=new Sheep();
        sheep.setAge(3);
        sheep.setName("肖恩");
        //克隆
        Sheep sheep1 = sheep.clone();
        Sheep sheep2=sheep.clone();
        System.out.println(sheep1);
        System.out.println(sheep2);
        System.out.println(sheep1==sheep2);

在這里插入圖片描述

結論

克隆出來的對象,它們的內存地址均不同,說明不是同一個對象,克隆成功,克隆僅僅通過調用 super.clone() 即可。

看一眼 Object#clone 方法

protected native Object clone() throws CloneNotSupportedException;

這是一個 native 關鍵字修飾的方法

一般而言,Java語言中的clone()方法滿足:

  • 對任何對象x,都有 x.clone() != x,即克隆對象與原型對象不是同一個對象;
  • 對任何對象x,都有 x.clone().getClass() == x.getClass(),即克隆對象與原型對象的類型一樣;
  • 如果對象x的 equals() 方法定義恰當,那么 x.clone().equals(x) 應該成立。
  • 為了獲取對象的一份拷貝,我們可以直接利用Object類的clone()方法,具體步驟如下:

在派生類中覆蓋基類的 clone() 方法,并聲明為public;

在派生類的 clone() 方法中,調用 super.clone();

派生類需實現(xiàn)Cloneable接口。

此時,Object類相當于抽象原型類,所有實現(xiàn)了Cloneable接口的類相當于具體原型類。

深淺拷貝

pig類:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pig 
{
    String name;
    Integer age;
}

sheep類:

//實現(xiàn)Cloneable接口
@Data
public class Sheep implements Cloneable
{
    private String name;
    private Integer age;
    private  Pig pig;
    //重寫Object的clone方法
    @Override
    protected Sheep clone() throws CloneNotSupportedException
    {
        Sheep sheep=null;
        sheep=(Sheep)super.clone();
        return sheep;
    }
}

客戶端進行克隆:

public class test
{
    @Test
    public void test() throws CloneNotSupportedException {
        //創(chuàng)建原型對象
        Sheep sheep=new Sheep();
        sheep.setAge(3);
        sheep.setName("肖恩");
        sheep.setPig(new Pig("大忽悠",3));
        //克隆
        Sheep sheep1 = sheep.clone();
        Sheep sheep2=sheep.clone();
        System.out.println(sheep1);
        System.out.println(sheep2);
        System.out.println(sheep1==sheep2);
        System.out.println("==============================");
        System.out.println(sheep1.getPig()==sheep2.getPig());
    }
}

在這里插入圖片描述

這里對Sheep類里面的引用類型Pig的克隆方式只是簡單的地址拷貝,即淺拷貝操作

深淺拷貝探討

淺克?。?/strong>

  • 在淺克隆中,如果原型對象的成員變量是值類型,將復制一份給克隆對象;如果原型對象的成員變量是引用類型,則將引用對象的地址復制一份給克隆對象,也就是說原型對象和克隆對象的成員變量指向相同的內存地址。
  • 簡單來說,在淺克隆中,當對象被復制時只復制它本身和其中包含的值類型的成員變量,而引用類型的成員對象并沒有復制。
  • 在Java語言中,通過覆蓋Object類的clone()方法可以實現(xiàn)淺克隆

深克?。?/strong>

  • 在深克隆中,無論原型對象的成員變量是值類型還是引用類型,都將復制一份給克隆對象,深克隆將原型對象的所有引用對象也復制一份給克隆對象。
  • 簡單來說,在深克隆中,除了對象本身被復制外,對象所包含的所有成員變量也將復制。
  • 在Java語言中,如果需要實現(xiàn)深克隆,可以通過序列化(Serialization)等方式來實現(xiàn)。需要注意的是能夠實現(xiàn)序列化的對象其類必須實現(xiàn)Serializable接口,否則無法實現(xiàn)序列化操作。

實現(xiàn)深克隆的方式一 : 手動對引用對象進行克隆

Pig類首先需要實現(xiàn)克隆即可,并重寫clone方法:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pig implements Cloneable
{
    String name;
    Integer age;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

sheep類:

//實現(xiàn)Cloneable接口
@Data
public class Sheep implements Cloneable
{
    private String name;
    private Integer age;
    private  Pig pig;
    //重寫Object的clone方法
    @Override
    protected Sheep clone() throws CloneNotSupportedException
    {
        Sheep sheep=null;
        sheep=(Sheep)super.clone();
        sheep.pig=(Pig)sheep.pig.clone();
        return sheep;
    }
}

在這里插入圖片描述

實現(xiàn)深克隆的方式二 :序列化

對象可以序列化的前提是實現(xiàn)了Serializable接口,這里Sheep和Pig都需要實現(xiàn)該接口

pig類:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pig implements Serializable
{
    String name;
    Integer age;
}

sheep類:

//實現(xiàn)Cloneable接口
@Data
public class Sheep implements Serializable
{
    private String name;
    private Integer age;
    private  Pig pig;
 //序列化方式完成深拷貝
    public Sheep deepClone() throws IOException, ClassNotFoundException {
        //先將要序列化的對象寫入流中
        ByteArrayOutputStream baot=new ByteArrayOutputStream();
        //ObjectOutputStream構造函數(shù)的參數(shù)是,將對象流寫入到哪里
        ObjectOutputStream oot=new ObjectOutputStream(baot);
          oot.writeObject(this);
          //將序列化的對象從流中讀取出來
        ByteArrayInputStream bait=new ByteArrayInputStream(baot.toByteArray());
        ObjectInputStream oit=new ObjectInputStream(bait);
        return (Sheep) oit.readObject();
    }
}

在這里插入圖片描述

原型模式對單例模式的破壞

餓漢式單例模式如下:

public class HungrySingleton implements Serializable, Cloneable {
    private final static HungrySingleton hungrySingleton;
    static {
        hungrySingleton = new HungrySingleton();
    }
    private HungrySingleton() 
    {}
    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
    private Object readResolve() {
        return hungrySingleton;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

使用反射獲取對象,測試如下

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        HungrySingleton hungrySingleton = HungrySingleton.getInstance();
        Method method = hungrySingleton.getClass().getDeclaredMethod("clone");
        method.setAccessible(true);
        HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton);
        System.out.println(hungrySingleton);
        System.out.println(cloneHungrySingleton);
    }
}

輸出

com.designpattern.HungrySingleton@34c45dca
com.designpattern.HungrySingleton@52cc8049

可以看到,通過原型模式,我們把單例模式給破壞了,現(xiàn)在有兩個對象了

為了防止單例模式被破壞,我們可以:不實現(xiàn) Cloneable 接口;或者把 clone 方法改為如下

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return getInstance();
    }

優(yōu)缺點

原型模式的主要優(yōu)點如下:

  • 當創(chuàng)建新的對象實例較為復雜時,使用原型模式可以簡化對象的創(chuàng)建過程,通過復制一個已有實例可以提高新實例的創(chuàng)建效率。
  • 擴展性較好,由于在原型模式中提供了抽象原型類,在客戶端可以針對抽象原型類進行編程,而將具體原型類寫在配置文件中,增加或減少產(chǎn)品類對原有系統(tǒng)都沒有任何影響。
  • 原型模式提供了簡化的創(chuàng)建結構,工廠方法模式常常需要有一個與產(chǎn)品類等級結構相同的工廠等級結構,而原型模式就不需要這樣,原型模式中產(chǎn)品的復制是通過封裝在原型類中的克隆方法實現(xiàn)的,無須專門的工廠類來創(chuàng)建產(chǎn)品。
  • 可以使用深克隆的方式保存對象的狀態(tài),使用原型模式將對象復制一份并將其狀態(tài)保存起來,以便在需要的時候使用(如恢復到某一歷史狀態(tài)),可輔助實現(xiàn)撤銷操作。

原型模式的主要缺點如下:

  • 需要為每一個類配備一個克隆方法,而且該克隆方法位于一個類的內部,當對已有的類進行改造時,需要修改源代碼,違背了“開閉原則”。
  • 在實現(xiàn)深克隆時需要編寫較為復雜的代碼,而且當對象之間存在多重的嵌套引用時,為了實現(xiàn)深克隆,每一層對象對應的類都必須支持深克隆,實現(xiàn)起來可能會比較麻煩。 適用場景
  • 創(chuàng)建新對象成本較大(如初始化需要占用較長的時間,占用太多的CPU資源或網(wǎng)絡資源),新的對象可以通過原型模式對已有對象進行復制來獲得,如果是相似對象,則可以對其成員變量稍作修改。
  • 如果系統(tǒng)要保存對象的狀態(tài),而對象的狀態(tài)變化很小,或者對象本身占用內存較少時,可以使用原型模式配合備忘錄模式來實現(xiàn)。
  • 需要避免使用分層次的工廠類來創(chuàng)建分層次的對象,并且類的實例對象只有一個或很少的幾個組合狀態(tài),通過復制原型對象得到新實例可能比使用構造函數(shù)創(chuàng)建一個新實例更加方便。

原型模式在Spring中的應用場景

在Spring中,用戶也可以采用原型模式來創(chuàng)建新的Bean實例,從而實現(xiàn)每次獲取的是通過克隆生成的新實例,對其進行修改時對原有實例對象不造成任何影響。

這里的原型模式,也就是常說的Spring中的多實例模式,Spring中還有大家熟知的單實例模式,即Sigleton

總結

在這里插入圖片描述

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!

相關文章

  • Java OkHttp框架源碼深入解析

    Java OkHttp框架源碼深入解析

    okhttp是一個第三方類庫,用于android中請求網(wǎng)絡。這是一個開源項目,是安卓端最火熱的輕量級框架,由移動支付Square公司貢獻(該公司還貢獻了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient
    2022-08-08
  • 詳解SSM框架下結合log4j、slf4j打印日志

    詳解SSM框架下結合log4j、slf4j打印日志

    本篇文章主要介紹了詳解SSM框架下結合log4j、slf4j打印日志,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • SpringBoot與Spring中數(shù)據(jù)緩存Cache超詳細講解

    SpringBoot與Spring中數(shù)據(jù)緩存Cache超詳細講解

    我們知道內存讀取速度遠大于硬盤讀取速度,當需要重復獲取相同數(shù)據(jù)時,一次一次的請求數(shù)據(jù)庫或者遠程服務,導致在數(shù)據(jù)庫查詢或者遠程方法調用上小號大量的時間,最終導致程序性能降低,這就是數(shù)據(jù)緩存要解決的問題,學過計算機組成原理或者操作系統(tǒng)的同學們應該比較熟悉
    2022-10-10
  • Java中遞歸、循環(huán)的優(yōu)劣分析

    Java中遞歸、循環(huán)的優(yōu)劣分析

    這篇文章主要給大家介紹了關于Java中遞歸、循環(huán)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用Java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • 修改request的parameter的幾種方式總結

    修改request的parameter的幾種方式總結

    這篇文章主要介紹了修改request的parameter的幾種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • jdk線程池的實現(xiàn)

    jdk線程池的實現(xiàn)

    本文主要介紹了jdk線程池的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • .idea文件夾里面iml文件的作用及說明

    .idea文件夾里面iml文件的作用及說明

    這篇文章主要介紹了.idea文件夾里面iml文件的作用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 使用Java填充Word模板的方法詳解

    使用Java填充Word模板的方法詳解

    Java填充Word模板是一種將動態(tài)數(shù)據(jù)插入到Word文檔模板中生成最終文檔的過程,通常用于批量創(chuàng)建包含個人信息、報告結果或其他動態(tài)內容的文檔,本文給大家介紹了使用Java填充Word模板的方法,需要的朋友可以參考下
    2024-07-07
  • MyBatis傳入多個參數(shù)時parameterType的寫法

    MyBatis傳入多個參數(shù)時parameterType的寫法

    這篇文章主要介紹了MyBatis傳入多個參數(shù)時parameterType的寫法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Java多線程同步工具類CountDownLatch詳解

    Java多線程同步工具類CountDownLatch詳解

    這篇文章主要介紹了Java多線程同步工具類CountDownLatch詳解,CountDownLatch是一個多線程同步工具類,在多線程環(huán)境中它允許多個線程處于等待狀態(tài),直到前面的線程執(zhí)行結束
    2022-06-06

最新評論