首頁 > 軟體

Java 設計模式以虹貓藍兔的故事講解原型模式

2022-04-11 10:01:55

什麼是原型模式

原型(Prototype)模式的定義如下: 用一個已經建立的範例作為原型,通過複製該原型物件來建立一個和原型相同或相似的新物件。在這裡,原型範例指定了要建立的物件的種類。用這種方式建立物件非常高效,根本無須知道物件建立的細節。例如,Windows 作業系統的安裝通常較耗時,如果複製就快了很多。在生活中複製的例子非常多,這裡不一一列舉了。

優點

1、Java 自帶的原型模式基於記憶體二進位制流的複製,在效能上比直接 new 一個物件更加優良。

2、可以使用深克隆方式儲存物件的狀態,使用原型模式將物件複製一份,並將其狀態儲存起來,簡化了建立物件的過程,以便在需要的時候使用(例如恢復到歷史某一狀態),可輔助實現復原操作。

缺點

1、需要為每一個類都設定一個 clone 方法

2、clone 方法位於類的內部,當對已有類進行改造的時候,需要修改程式碼,違背了開閉原則。

3、當實現深克隆時,需要編寫較為複雜的程式碼,而且當物件之間存在多重巢狀參照時,為了實現深克隆,每一層物件對應的類都必須支援深克隆,實現起來會比較麻煩。因此,深克隆、淺克隆需要運用得當。

應用場景

在有些系統中,存在大量相同或相似物件的建立問題,如果用傳統的建構函式來建立物件,會比較複雜且耗時耗資源,用原型模式生成物件就很高效,就像孫悟空拔下猴毛輕輕一吹就變出很多孫悟空一樣簡單。

淺克隆

案例:克隆虹貓

淺克隆一個虹貓,外表特徵一樣,但是隻有一個靈魂。

克隆虹貓身體受到傷害,本體虹貓不受影響。

克隆虹貓精神受到傷害,本體虹貓也受到同樣的傷害。

程式碼實現

虹貓靈魂狀態類

這裡宣告了虹貓的靈魂狀態

public class Hong {
    //虹貓的靈魂狀態
    private String lh;
    Hong(String lh) {
        this.lh = lh;
    }
    Hong() {
    }

    public String getLh() {
        return lh;
    }

    public void setLh(String lh) {
        this.lh = lh;
    }

}

虹貓個體類

實現了Cloneable 介面,並且有虹貓的身體狀態和靈魂狀態等屬性。

public class Qian implements Cloneable {
    private String shou;
    private String jiao;
    private String yan;
    private Hong hong;

    Qian() {
    }

    Qian(String shou, String jiao, String yan, Hong hong) {
        this.hong = hong;
        this.shou = shou;
        this.jiao = jiao;
        this.yan = yan;
    }

    public Qian clone() throws CloneNotSupportedException {
        return (Qian) super.clone();
    }

    public String getShou() {
        return shou;
    }

    public void setShou(String shou) {
        this.shou = shou;
    }

    public String getJiao() {
        return jiao;
    }

    public void setJiao(String jiao) {
        this.jiao = jiao;
    }

    public String getYan() {
        return yan;
    }

    public void setYan(String yan) {
        this.yan = yan;
    }

    public Hong getHong() {
        return hong;
    }

    public void setHong(Hong hong) {
        this.hong = hong;
    }

}

測試類

這裡測試一下淺克隆的效果:

淺克隆一個虹貓,外表特徵一樣,但是隻有一個靈魂。

克隆虹貓身體受到傷害,本體虹貓不受影響。

克隆虹貓精神受到傷害,本體虹貓也受到同樣的傷害。

public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Qian qian = new Qian("兩隻手", "兩隻腳", "兩隻眼", new Hong("完整的靈魂"));
        Qian qian1 = qian.clone();
        System.out.printf("虹貓少俠本體的身體狀態:%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan());
        System.out.println();
        System.out.printf("虹貓少俠一號的身體狀態:%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan());

    }
}

克隆出來了一個虹貓一號,所有屬性都一模一樣

public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Qian qian = new Qian("兩隻手", "兩隻腳", "兩隻眼", new Hong("完整的靈魂"));
        Qian qian1 = qian.clone();
        qian1.getHong().setLh("靈魂受到攻擊");
        qian1.setJiao("斷了一隻腳");
        System.out.printf("虹貓少俠本體的身體狀態:%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan());
        System.out.println();
        System.out.printf("虹貓少俠一號的身體狀態:%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan());
    }
}

這裡克隆虹貓的腳和靈魂都受到了傷害,本體虹貓的身體沒有受到影響,但是靈魂卻受到了傷害。

總結

一、為什麼淺克隆中虹貓一號的腳受到了傷害,本體虹貓卻沒受到傷害?

二、為什麼淺克隆中虹貓一號的靈魂受到了傷害,本體虹貓也受到了傷害?

因為建立一個新物件,新物件的屬性和原來物件完全相同,對於非基本型別屬性,仍指向原有屬性所指向的物件的記憶體地址。 兩個虹貓的靈魂指向同一個記憶體地址,所以儲存的是同一個靈魂。

深克隆

案例:克隆虹貓

深克隆一個虹貓,外表特徵一樣,都有獨立靈魂。

克隆虹貓身體受到傷害,本體虹貓不受影響。

克隆虹貓精神受到傷害,本體虹貓也不受影響。

程式碼實現

虹貓靈魂狀態類

這裡宣告了虹貓的靈魂狀態,並且實現了Cloneable 介面,克隆一個虹貓靈魂

public class Hong implements Cloneable {
    //虹貓的靈魂狀態
    private String lh;

    Hong(String lh) {
        this.lh = lh;
    }

    Hong() {
    }

    public Hong clone() throws CloneNotSupportedException {
        return (Hong) super.clone();
    }

    public String getLh() {
        return lh;
    }

    public void setLh(String lh) {
        this.lh = lh;
    }

}

虹貓個體類

重寫了clone方法,在clone方法中呼叫了hong.clone()方法克隆了一個虹貓靈魂

public class Qian implements Cloneable {
    private String shou;
    private String jiao;
    private String yan;
    private Hong hong;

    Qian() {
    }

    Qian(String shou, String jiao, String yan, Hong hong) {
        this.hong = hong;
        this.shou = shou;
        this.jiao = jiao;
        this.yan = yan;
    }

    public Qian clone() throws CloneNotSupportedException {
        Qian qian = (Qian) super.clone();
        hong = hong.clone();
        return qian;

    }

    public String getShou() {
        return shou;
    }

    public void setShou(String shou) {
        this.shou = shou;
    }

    public String getJiao() {
        return jiao;
    }

    public void setJiao(String jiao) {
        this.jiao = jiao;
    }

    public String getYan() {
        return yan;
    }

    public void setYan(String yan) {
        this.yan = yan;
    }

    public Hong getHong() {
        return hong;
    }

    public void setHong(Hong hong) {
        this.hong = hong;
    }

}

測試類

這裡測試一下淺克隆的效果:

深克隆一個虹貓,外表特徵一樣,都有獨立靈魂。

克隆虹貓身體受到傷害,本體虹貓不受影響。

克隆虹貓精神受到傷害,本體虹貓也不受影響。

public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Qian qian = new Qian("兩隻手", "兩隻腳", "兩隻眼", new Hong("完整的靈魂"));
        Qian qian1 = qian.clone();
        qian1.getHong().setLh("靈魂受到攻擊");
        qian1.setJiao("斷了一隻腳");
        System.out.printf("虹貓少俠本體的身體狀態:%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan());
        System.out.println();
        System.out.printf("虹貓少俠一號的身體狀態:%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan());
    }
}

深克隆出的虹貓完全是個獨立的個體,再也不用受限制了。

總結

深克隆:建立一個新物件,屬性中參照的其他物件也會被克隆,不再指向原有物件地址。

到此這篇關於Java 設計模式以虹貓藍兔的故事講解原型模式的文章就介紹到這了,更多相關Java 原型模式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com