首頁 > 軟體

Java的原型設計模式其實真的不難

2022-03-29 16:00:11

原型設計模式

我們知道在有些程式設計中,程式內有大量相同或相似物件的建立問題,如果用傳統的建構函式或者重新去new來建立物件,會比較複雜且耗時耗資源,用原型模式生成物件就很高效。也就是我們當有一個原型的物件後,如果還需要一個或多個相同或者相似的物件,我們就也可以採用原型模式來設計。

舉例說明:

在之前文章中講的的可樂,我們知道可樂有很多配料,當剛研究出配方的時候我們去生產可樂,就需要往水裡加各種各樣的配料(相當於建構函式,然後傳入引數),當之後才去生產可樂如果還是採用這種構造方法來生成的話,很麻煩且需要資源。我們把已經配好的作為一個可樂濃縮液,下次直接使用這個濃縮液就可以了(這就是原型設計模式裡面的複製,直接複製濃縮液這個物件就可以)

1、原型設計模式的定義

用一個已經建立的範例作為原型,通過複製該原型物件來建立一個和原型相同或相似的新物件。在這裡,原型範例指定了要建立的物件的種類。用這種方式建立物件非常高效,根本無須知道物件建立的細節。

型別: 建立型

2、原型設計模式的優缺點

優點:

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

2.可以使用深克隆方式儲存物件的狀態,使用原型模式將物件複製一份,並將其狀態儲存起來,簡化了建立物件的過程

缺點:

1.需要為每一個類都設定一個 clone 方法 (淺克隆

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

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

3、原型模式的結構

結構由三部分組成:

  • 抽象原型類:規定了具體原型物件必須實現的介面
  • 具體原型類:實現抽象原型類的 clone() 方法,它是可被複制的物件
  • 存取類:使用具體原型類中的 clone() 方法來複制新的物件

4、淺克隆和深克隆的區別 

  • 淺克隆: 建立一個新物件,新物件的屬性和原來物件完全相同,對於非基本型別屬性,仍指向原有屬性所指向的物件的記憶體地址
  • 深克隆: 建立一個新物件,屬性中參照的其他物件也會被克隆,不再指向原有物件地址

5、原型設計模式的簡單程式碼實現

首先我們先來一個簡單的原型模式

有一個具體原型類:實現抽象原型類的 clone() 方法,它是可被複制的物件

/**
 *
 *具體原型類,需要實現Cloneable介面
 */
public class RealizeType implements Cloneable{

    RealizeType(){
        System.out.println("具體原型類建立成功");
    }

    public Object Clone() throws CloneNotSupportedException {
        System.out.println("具體原型類複製成功");
        return (RealizeType)super.clone();
    }
}

我們先來看一下需要實現Cloneable介面裡面有什麼?

其實這個介面裡面什麼都沒有,只是一個程式碼規範而已

測試類:

/**
 * 測試類:
 * 第一個類物件通過new來建立
 * 第二個物件通過clone()的方法來建立
 * 最後判斷兩個物件地址是否一致
 */
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        RealizeType realizeType1 = new RealizeType();
        RealizeType realizeType2 = (RealizeType) realizeType1.Clone();
        boolean a = realizeType1==realizeType2;
        System.out.println("兩個物件地址是否相等:" + a);
        
    }
}

如果兩個物件的地址是一樣的,說明沒有複製成功,若地址不一樣,則複製成功:

具體原型類建立成功具體原型複製成功兩個物件地址是否相等:false

這樣通過Clone()的方法複製了原型物件

6、原型設計模式的案例

公司裡面每個階段都會頒發榮譽,但是我們知道榮譽證書這個物件的模板已經確定好了,是固定不變的,我們只需要寫入不同的資訊即可:姓名、部門、獲得的榮譽資訊等等

獎狀類:

/**
 * 獎狀榮譽類:相當於具體原型類,可以被克隆使用
 */
public class Honor implements Cloneable{

    String Department; //部門
    String name; //姓名
    String info; //獲獎資訊

    //構造方法
    public Honor(String college, String name, String info) {
        this.Department = college;
        this.name = name;
        this.info = info;
    }

    //getset

    public String getCollege() {
        return Department;
    }

    public void setCollege(String college) {
        this.Department = college;
    }

    public String getName() {
        return name;
    }

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

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "獎狀{" +
                "恭喜" + Department+
                "部門" + name  +
                "同志獲得" + info +
                '}';
    }

    public Object clone() throws CloneNotSupportedException {
        System.out.println("榮譽拷貝成功!");
        return (Honor)super.clone();
    }
}

測試類:

public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Honor h1 = new Honor("銷售部","張三","最佳銷售");
        //第一個物件通過new來建立
        System.out.println(h1.toString());

        //通過clone來拷貝
        Honor h2 = (Honor) h1.clone();

        //更換名字
        h2.setName("李四");
        System.out.println(h2.toString());

        Honor h3 = (Honor) h1.clone();
        h3.setInfo("最佳員工");
        h3.setName("王五");
        h3.setCollege("人事部");
        System.out.println(h3.toString());

    }
}


輸出:

獎狀{恭喜銷售部部門張三同志獲得最佳銷售}
榮譽拷貝成功!
獎狀{恭喜銷售部部門李四同志獲得最佳銷售}
榮譽拷貝成功!
獎狀{恭喜人事部部門王五同志獲得最佳員工}

通過原型設計模式的方法,我們在建立相似物件的時候,就不需要使用建構函式new一個新物件,通過clone的方法即可,也可以任意修改引數(使用get/set)

7、原型設計模式的應用場景

1.物件之間相同或相似,即只是個別的幾個屬性不同的時候

2.建立物件成本較大,比如初始化時間長,需要優化資源等

3.建立一個物件需要繁瑣的資料準備或存取許可權等,需要提高效能或者提高安全性

4.系統中大量使用該類物件,且各個呼叫者都需要給它的屬性重新賦值

在Java框架Spring中原型設計模式應用的也很多,所以這個模式還是有很多用處的

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!


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