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

Java?深入理解創(chuàng)建型設計模式之原型模式

 更新時間:2022年02月16日 16:19:57   作者:張起靈-小哥  
原型(Prototype)模式的定義如下:用一個已經創(chuàng)建的實例作為原型,通過復制該原型對象來創(chuàng)建一個和原型相同或相似的新對象。在這里,原型實例指定了要創(chuàng)建的對象的種類。用這種方式創(chuàng)建對象非常高效,根本無須知道對象創(chuàng)建的細節(jié)

1.思考問題

現(xiàn)在有一只羊 tom,姓名為: tom,年齡為:1,顏色為:白色,請編寫程序創(chuàng)建和 tom羊屬性完全相同的10只羊。

按照傳統(tǒng)的思路來,我們可能會按照下面的方式去寫。

那么這種寫法的優(yōu)缺點自然而然就出來了:

  • 優(yōu)點是比較好理解,簡單易操作。
  • 缺點是在創(chuàng)建新的對象時,總是需要重新獲取原始對象的屬性,如果創(chuàng)建的對象比較復雜時,效率較低??偸切枰匦鲁跏蓟瘜ο?,而不是動態(tài)地獲得對象運行時的狀態(tài),不夠靈活。
  • 改進的思路分析:Java中Object類是所有類的根類,Object類提供了一個 clone()方法,該方法可以將一個Java對象復制一份,但是需要實現(xiàn)clone的Java類必須要實現(xiàn)一個接口Cloneable,該接口表示該類能夠復制且具有復制的能力  =>  原型模式。

2.什么是原型模式?

  • 原型模式(Prototype模式)是指:  用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型,創(chuàng)建新的對象。
  • 原型模式是一種創(chuàng)建型設計模式,允許一個對象再創(chuàng)建另外一個可定制的對象,無需知道如何創(chuàng)建的細節(jié)。
  • 工作原理是:  通過將一個原型對象傳給那個要發(fā)動創(chuàng)建的對象,這個要發(fā)動創(chuàng)建的對象通過請求原型對象拷貝它們自己來實施創(chuàng)建,即對象.clone()。

原型模式相關的類圖如下:

3.克隆羊多莉案例代碼(淺拷貝)

這里由于我是新建的普通Java項目,并不是maven項目,所以沒法加lombok依賴。那么這里的構造器、setter/getter方法顯得這個類的篇幅比較長。。。

package com.szh.prototype.shallowclone;
 
public class Sheep implements Cloneable {
    private String name;
    private Integer age;
    private String color;
    private Sheep friend;
 
    public Sheep(String name, Integer age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }
 
    public Sheep(String name, Integer age, String color, Sheep friend) {
        this.name = name;
        this.age = age;
        this.color = color;
        this.friend = friend;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 
    public String getColor() {
        return color;
    }
 
    public void setColor(String color) {
        this.color = color;
    }
 
    public Sheep getFriend() {
        return friend;
    }
 
    public void setFriend(Sheep friend) {
        this.friend = friend;
    }
 
    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                ", friend=" + friend +
                '}';
    }
 
    //克隆該實例,使用默認的clone方法來完成
    @Override
    protected Object clone()  {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}
package com.szh.prototype.shallowclone;
 
public class MainTest {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("多莉",5,"黑白相間",new Sheep("喜羊羊",1,"白色"));
 
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        Sheep sheep4 = (Sheep) sheep.clone();
        Sheep sheep5 = (Sheep) sheep.clone();
 
        System.out.println(sheep + "  sheep.friend.hashCode = " + sheep.getFriend().hashCode());
        System.out.println(sheep2 + "  sheep2.friend.hashCode = " + sheep2.getFriend().hashCode());
        System.out.println(sheep3 + "  sheep3.friend.hashCode = " + sheep3.getFriend().hashCode());
        System.out.println(sheep4 + "  sheep4.friend.hashCode = " + sheep4.getFriend().hashCode());
        System.out.println(sheep5 + "  sheep5.friend.hashCode = " + sheep5.getFriend().hashCode());
    }
}

從上面的運行結果中可以看到,Sheep類中的前三個成員屬性都可以成功的拷貝,但是最后一個friend,它表示羊的朋友(也是Sheep類型,就是引用類型了)。而當我們拷貝完成之后,應該來說都是不一樣的新的對象,但是它們中的friend屬性的hashCode居然是一樣的?。?!    這里我們就要來聊一聊深拷貝和淺拷貝了。

淺拷貝:

  • 對于數(shù)據(jù)類型是基本數(shù)據(jù)類型的成員變量,淺拷貝會直接進行值傳遞,也就是將該屬性值復制一份給新的對象。
  • 對于數(shù)據(jù)類型是引用數(shù)據(jù)類型的成員變量,比如說成員變量是某個數(shù)組、某個類對象等,那么淺拷貝會進行引用傳遞,也就是只是將該成員變量的引用值(內存地址〉復制一份給新的對象。因為實際上兩個對象的該成員變量都指向同一個實例。在這種情況下,在一個對象中修改該成員變量會影響到另一個對象的該成員變量值。
  • 前面我們克隆羊就是淺拷貝。淺拷貝是使用默認的clone()方法來實現(xiàn):sheep= (Sheep) super.clone();

深拷貝:

  • 復制對象的所有基本數(shù)據(jù)類型的成員變量值。
  • 為所有引用數(shù)據(jù)類型的成員變量申請存儲空間,并復制每個引用數(shù)據(jù)類型成員變量所引用的對象,直到該對象可達的所有對象。也就是說,對象進行深拷貝要對整個對象(包括對象的引用類型)進行拷貝。
  • 深拷貝實現(xiàn)方式1:  重寫clone方法來實現(xiàn)深拷貝。
  • 深拷貝實現(xiàn)方式2:  通過對象序列化實現(xiàn)深拷貝(推薦)。

4.深拷貝代碼案例

package com.szh.prototype.deepclone;
 
import java.io.Serializable;
 
public class DeepCloneableTarget implements Serializable, Cloneable {
 
    private static final long serialVersionUID = 1L;
    private String cloneName;
    private String cloneClass;
 
    public DeepCloneableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }
 
    @Override
    public String toString() {
        return "DeepCloneableTarget{" +
                "cloneName='" + cloneName + '\'' +
                ", cloneClass='" + cloneClass + '\'' +
                '}';
    }
 
    //因為該類的屬性,都是String , 因此我們這里使用默認的clone完成即可
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
package com.szh.prototype.deepclone;
 
import java.io.*;
 
public class DeepPrototype implements Serializable, Cloneable {
 
    public String name; //String 屬性
    public DeepCloneableTarget deepCloneableTarget;// 引用類型
 
    public DeepPrototype() {
        super();
    }
 
    @Override
    public String toString() {
        return "DeepPrototype{" +
                "name='" + name + '\'' +
                ", deepCloneableTarget=" + deepCloneableTarget +
                '}';
    }
 
    //深拷貝 - 方式 1 使用clone 方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object deep = null;
        deep = super.clone();
        DeepPrototype deepPrototype = (DeepPrototype) deep;
        deepPrototype.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
        return deepPrototype;
    }
 
    //深拷貝 - 方式2 通過對象的序列化實現(xiàn) (推薦)
    public Object deepClone() {
        //創(chuàng)建流對象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
 
        try {
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
 
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepPrototype copyObj = (DeepPrototype) ois.readObject();
            return copyObj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //關閉流
            try {
                ois.close();
                bis.close();
                oos.close();
                bos.close();
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }
    }
}
package com.szh.prototype.deepclone;
 
public class MainTest {
    public static void main(String[] args) throws Exception {
        DeepPrototype prototype = new DeepPrototype();
        prototype.name = "張起靈";
        prototype.deepCloneableTarget = new DeepCloneableTarget("小哥","悶油瓶");
 
        //方式1 完成深拷貝
        DeepPrototype prototype2 = (DeepPrototype) prototype.clone();
        System.out.println("方式1 完成深拷貝");
        System.out.println("prototype.name = " + prototype.name + ", prototype.deepCloneableTarget = " + prototype.deepCloneableTarget);
        System.out.println("prototype.deepCloneableTarget.hashCode = " + prototype.deepCloneableTarget.hashCode());
        System.out.println("-------------------------------------------------------");
        System.out.println("prototype2.name = " + prototype2.name + ", prototype2.deepCloneableTarget = " + prototype2.deepCloneableTarget);
        System.out.println("prototype2.deepCloneableTarget.hashCode = " + prototype2.deepCloneableTarget.hashCode());
        System.out.println("==============================================================================");
 
        //方式2 完成深拷貝
        DeepPrototype prototype3 = (DeepPrototype) prototype.deepClone();
        System.out.println("方式2 完成深拷貝");
        System.out.println("prototype.name = " + prototype.name + ", prototype.deepCloneableTarget = " + prototype.deepCloneableTarget);
        System.out.println("prototype.deepCloneableTarget.hashCode = " + prototype.deepCloneableTarget.hashCode());
        System.out.println("-------------------------------------------------------");
        System.out.println("prototype3.name = " + prototype3.name + ", prototype3.deepCloneableTarget = " + prototype3.deepCloneableTarget);
        System.out.println("prototype3.deepCloneableTarget.hashCode = " + prototype3.deepCloneableTarget.hashCode());
    }
}

5.原型模式總結

  • 創(chuàng)建新的對象比較復雜時,可以利用原型模式簡化對象的創(chuàng)建過程,同時也能夠提高效率。
  • 不用重新初始化對象,而是動態(tài)地獲得對象運行時的狀態(tài)。
  • 如果原始對象發(fā)生變化(增加或者減少屬性),其它克隆對象的也會發(fā)生相應的變化,無需修改代碼。
  • 在實現(xiàn)深克隆的時候可能需要比較復雜的代碼。
  • 缺點:  需要為每一個類配備一個克隆方法,這對全新的類來說不是很難,但對已有的類進行改造時,需要修改其源代碼,違背了ocp原則。

到此這篇關于Java 深入理解創(chuàng)建型設計模式之原型模式的文章就介紹到這了,更多相關Java 原型模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java AtomicInteger類使用方法實例講解

    Java AtomicInteger類使用方法實例講解

    這篇文章主要介紹了Java AtomicInteger類使用方法實例講解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • springboot 自定義權限標簽(tld),在freemarker引用操作

    springboot 自定義權限標簽(tld),在freemarker引用操作

    這篇文章主要介紹了springboot 自定義權限標簽(tld),在freemarker引用操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java將word文件轉成pdf文件的操作方法

    Java將word文件轉成pdf文件的操作方法

    這篇文章主要介紹了Java將word文件轉成pdf文件的操作方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • 如何基于java隨機獲取不重復數(shù)值

    如何基于java隨機獲取不重復數(shù)值

    這篇文章主要介紹了如何基于java隨機獲取不重復數(shù)值,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot整合freemarker的講解

    SpringBoot整合freemarker的講解

    今天小編就為大家分享一篇關于SpringBoot整合freemarker的講解,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Idea插件安裝和管理方式

    Idea插件安裝和管理方式

    這篇文章主要介紹了Idea插件安裝和管理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java面試題之HashMap 的 hash 方法原理是什么

    Java面試題之HashMap 的 hash 方法原理是什么

    那天,小二去蔚來面試,面試官老王一上來就問他:HashMap 的 hash 方法的原理是什么?當時就把裸面的小二給蚌埠住了,這篇文章將詳細解答該題目
    2021-11-11
  • SpringBoot中整合Shiro實現(xiàn)權限管理的示例代碼

    SpringBoot中整合Shiro實現(xiàn)權限管理的示例代碼

    這篇文章主要介紹了SpringBoot中整合Shiro實現(xiàn)權限管理的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java方法簽名的獲取實例代碼

    Java方法簽名的獲取實例代碼

    這篇文章主要介紹了Java方法簽名的獲取實例代碼,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Mac修改默認jdk版本的方法總結

    Mac修改默認jdk版本的方法總結

    這篇文章主要介紹了Mac修改默認jdk版本的相關資料,文中詳細介紹了如何將Java版本從Java?17降低到Java?8,并通過修改.bash_profile文件來永久生效,需要的朋友可以參考下
    2024-12-12

最新評論

镇原县| 蕉岭县| 丹巴县| 辛集市| 循化| 思南县| 莆田市| 谢通门县| 敦化市| 望城县| 略阳县| 栾川县| 兴文县| 台湾省| 南通市| 磐安县| 张北县| 庆安县| 石门县| 宜章县| 都昌县| 临邑县| 瓦房店市| 乌拉特后旗| 正镶白旗| 西华县| 油尖旺区| 永济市| 林芝县| 垫江县| 额尔古纳市| 榕江县| 佛冈县| 大名县| 阜南县| 大姚县| 华安县| 剑川县| 景谷| 夏邑县| 洱源县|