日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

原型模式(深克隆、浅克隆)

發布時間:2023/12/31 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 原型模式(深克隆、浅克隆) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上期回顧:建造者模式

文章目錄

  • 一、原型模式定義
  • 二、原型模式的結構與實現
  • 三、案例
    • (一)淺克隆
    • (二)深克隆
    • (三)淺克隆和深克隆的區別
  • 四、原型模式使用場景



一、原型模式定義

原型模式是一種創建型設計模式,Prototype模式允許一個對象再創建另外一個可定制的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實施創建。

二、原型模式的結構與實現

原型模式有以下三種角色:
1.抽象原型類(Prototype):規定了具體原型對象必須實現的接口。
2.具體原型類(Realizetype):實現抽象原型類的 clone() 方法,它是可被復制的對象。
3.訪問類(PrototypeTest):使用具體原型類中的 clone() 方法來復制新的對象

原型模式的克隆可以分為淺克隆和深克隆

淺克隆:創建一個新對象,新對象的屬性和原來對象完全相同,對于非基本類型屬性,仍指向原有屬性所指向的對象的內存地址。
深克隆:創建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。

Java中的Object類中提供clone()方法來實現淺克隆。Cloneable接口就是抽象原型類,而實現了Cloneable接口的子實現類就是具體的原型類。

原型模式設計如下:

//在這里抽象原型類是Cloneable接口 //具體原型類 public class Realizetype implements Cloneable{public Realizetype() {System.out.println("具體原型對象已創建成功!");}@Overrideprotected Realizetype clone() throws CloneNotSupportedException {System.out.println("具體原型已復制成功!");return (Realizetype) super.clone();} } //訪問類 public class Client {public static void main(String[] args) throws CloneNotSupportedException {//創建一個原型類對象Realizetype realizetype = new Realizetype();//得到原型對象的克隆對象Realizetype clone = realizetype.clone();//查看是否是同一個對象System.out.println("原型對象和克隆的對象是否是同一個對象:"+(realizetype == clone));} }

測試結果:
具體原型對象已創建成功!
具體原型已復制成功!
原型對象和克隆的對象是否是同一個對象:false

這里展示的原型模式只是一個簡單的克隆,抽象原型類就是Cloneable接口,具體原型類就是可被復制的對象,而訪問類就是使用克隆clone()來復制新的對象。

需要注意的是,單看測試結果我們會發現原型模式有以下幾個問題。

  • 克隆底層不是通過new對象實現的,因為調用clone()的時候并沒有打印出Realizetype 類的構造函數中的內容。
  • 原型對象和克隆的對象不是同一個對象

而且查看clone()源碼發現它是一個native本地方法,也是說它并不是由java語言實現的。

protected native Object clone() throws CloneNotSupportedException;

三、案例

用原型模式來實現以下需求:
假如某學校要對這一學期的社團指導老師頒發聘書,那么我現在就可以根據獎狀模板進行克隆,用原型模式設計思想實現。

原型對象:獎狀類

//原型對象:聘書 public class Letter implements Cloneable{private String name; //指導老師姓名public String getName() {return name;}public void setName(String name) {this.name = name;}public void show(){System.out.println("茲聘請 "+name+" 老師為 xxx 社團指導老師!");}@Overrideprotected Letter clone() throws CloneNotSupportedException {return (Letter)super.clone();} }

訪問類:測試

public class Test {public static void main(String[] args) throws CloneNotSupportedException {Letter letter = new Letter();//開始克隆Letter letter1 = letter.clone();//原型對象System.out.print("原型對象:");letter.setName("張三");letter.show();//克隆對象System.out.print("克隆后對象:");letter1.setName("李四");letter1.show();} }

運行結果:

原型對象: 茲聘請 張三 老師為 xxx 社團指導老師!
克隆后對象: 茲聘請 李四 老師為 xxx 社團指導老師!

這個例子比較簡單好理解,現在我在這個案例中引入深克隆和淺克隆的概念。

(一)淺克隆

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

1、首先我再創建一個社團類,里面有一個社團名稱的屬性

//社團類 public class Association {private String name ; //社團名稱public Association(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;} }

2、修改聘書類,加上一個社團類的對象屬性

//原型對象:聘書 public class Letter implements Cloneable{private String name; //指導老師姓名private Association association; //社團public Letter(String name, Association association) {this.name = name;this.association = association;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Association getAssociation() {return association;}public void setAssociation(Association association) {this.association = association;}public void show(){System.out.println("茲聘請 "+name+" 老師為 "+association.getName()+" 社團指導老師!");}@Overrideprotected Letter clone() throws CloneNotSupportedException {return (Letter)super.clone();} }

測試類:將原型對象聘書類進行克隆,然后打印出原型對象中Association引用地址和克隆后Association引用地址,判斷該引用地址是否發生改變

public class Test {public static void main(String[] args) throws CloneNotSupportedException {Association association = new Association("歌舞社");//拷貝之前的對象Letter letter = new Letter("張三",association);System.out.print("克隆前對象:");letter.show();//拷貝之后的對象Letter letter1 = letter.clone();System.out.print("克隆后對象:");letter1.show();//判斷System.out.println(letter.getAssociation() == letter1.getAssociation());System.out.println("克隆前Association對象的hashCode:"+letter.getAssociation().hashCode());System.out.println("克隆后Association對象的hashCode:"+letter1.getAssociation().hashCode());} }

輸出結果:

克隆前對象:茲聘請 張三 老師為 歌舞社 社團指導老師!
克隆后對象:茲聘請 張三 老師為 歌舞社 社團指導老師!
true
克隆前Association對象的hashCode:666988784
克隆后Association對象的hashCode:666988784

結果發現,letter.getAssociation() == letter1.getAssociation()結果返回true,說明克隆前后Letter類中持有的Association引用地址沒有發生改變,加上show()內容一樣,說明屬性也沒發生改變,這明顯符合我們對淺克隆的定義。而且打印出來的hashCode值相同,同樣證明了它們是引用的同一個地址。

由于指向同一個地址,那我對克隆后的對象修改屬性,原來的原型對象中的屬性也會發生變化嗎?
測試如下,將克隆的對象中原來的張三指導的“歌舞社”改為“足球社”,再查看未克隆前的原型對象是否發生了改變。

public class Test {public static void main(String[] args) throws CloneNotSupportedException {Association association = new Association("歌舞社");Letter letter = new Letter("張三",association);//原來System.out.println("原對象:");letter.show();//克隆并修改Letter clone = letter.clone();Association association1 = clone.getAssociation();association1.setName("足球社");//再次查看原來對象System.out.println("克隆對象修改后再次查看原來對象:");letter.show();} }

測試結果:

原對象:
茲聘請 張三 老師為 歌舞社 社團指導老師!


克隆對象修改后再次查看原來對象:
茲聘請 張三 老師為 足球社 社團指導老師!

發現修改克隆對象中的屬性,原對象也發生了同步改變。這再一次說明了淺克隆中,會把原型對象中成員變量為引用類型的引用地址也復制給克隆對象,且此引用對象的地址是共享給原型對象和克隆對象的。

總結:淺克隆只復制指向某個對象的引用,而不復制對象本身,新舊對象還是共享同一塊內存,修改對象會改到原對象

(二)深克隆

清楚了淺克隆例子后。再來回顧一下深克隆的定義 ---- 創建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。

這要如何實現?很簡單>

讓Association類實現Cloneable接口,重寫clone()方法

@Override protected Association clone() throws CloneNotSupportedException {return (Association) super.clone(); }

修改Letter類的clone()方法,加上對association的克隆

@Override protected Letter clone() throws CloneNotSupportedException {Letter letter = (Letter)super.clone();//拷貝Association對象letter.association= this.association.clone();return letter; }

測試結果:

原對象:
茲聘請 張三 老師為 歌舞社 社團指導老師!

克隆后對象:
茲聘請 張三 老師為 足球社 社團指導老師!

克隆對象修改后再次查看原來對象:
茲聘請 張三 老師為 歌舞社 社團指導老師!

經過這一頓操作后,修改克隆后對象的屬性,也不會影響到原對象,這就是深克隆,它將原型對象中的所有類型,無論是值類型還是引用類型,都復制了一份給克隆對象。

總結:深克隆對原型對象完全拷貝,但新對象跟原對象不共享內存,修改新對象不會改變原對象。

(三)淺克隆和深克隆的區別

最后用一張圖簡單的總結一下淺克隆和深克隆的區別

四、原型模式使用場景

原型模式(Prototype Pattern)是用于創建重復的對象,同時又能保證性能。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

它的使用場景如下:

1、資源優化場景。
2、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。
3、性能和安全要求的場景。
4、通過new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。
5、一個對象多個修改者的場景。
6、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。
7、在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然后由工廠方法提供給調用者。原型模式已經與 Java 融為渾然一體,大家可以隨手拿來使用。

總結

以上是生活随笔為你收集整理的原型模式(深克隆、浅克隆)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。