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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

什么是 “原型模式” ?

發布時間:2024/8/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 什么是 “原型模式” ? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:東風玖哥,小灰

來源:程序員小灰


—————? 第二天? —————


————————————


假如有一天,小灰被外星人抓走了,外星人要拿小灰做實驗,想了解小灰在吃得好、睡得好、玩得開心的場景下,與現實中小灰的生存狀態有什么區別。

于是,外星人克隆了幾個一模一樣的小灰:

就這樣,小灰的原型被留在現實中,而三個復制體分別提供了吃得好、睡得好、玩得開心三種不同環境,小灰的原型則不受三個復制體的影響。

過了一段時間,我們來觀察一下本體與分身的生存狀態:

在Java語言中,Object類實現了Cloneable接口,一個對象可以通過調用Clone()方法生成對象,這就是原型模式的典型應用。但需要注意的是,clone()方法并不是Cloneable接口里的,而是Object類里的,Cloneable是一個標識接口,標識這個類的對象是可被拷貝的,如果沒有實現Cloneable接口,卻調用了clone()方法,就會報錯。

//?protected?native?Object?clone()?throwsCloneNotSupportedException;protected?Object?clone()?throws CloneNotSupportedException?{if?(!(this?instanceof?Cloneable))?{throw?new?CloneNotSupportedException( "Class?"?+?getClass().getName()?+ "?doesn't?implement?Cloneable");}return?internalClone(); }//?Native?helper?method?for?cloning.private?native?Object?internalClone();

?

?

Java中的數據類型,分為基本類型和引用類型。在一個方法里的變量如果是基本類型的話,變量就直接存儲在這個方法的棧幀里,例如int、long等;而引用類型則在棧幀里存儲這個變量的指針,指向堆中該實體的地址,例如String、Array等。深拷貝和淺拷貝是只針對引用數據類型的。

?

比如一個方法有一個基本類型參數和一個引用類型參數,在方法體里對參數重新賦值,會影響傳入的引用類型參數,而不會影響基本類型參數,因為基本類型參數是值傳遞,而引用類型參數是引用傳遞。

先定義一個用戶類:

//?這是一個非常簡單的用戶類public?class?User?{private?String?name;private?int?age;public?User(String?name,?int?age)?{this.name=name;this.age=age;}public?String?getName()?{return?name;}public?void?setName(String?name)?{this.name?=?name;}public?int?getAge()?{return?age;}public?void?setAge(int?age)?{this.age?=?age;}@Overridepublic?String?toString()?{return?"User{name='"?+?name?+?",?age="?+?age?+'}';}} private?int?x=10;public?void?updateValue(int?value){value?=?3?*?value; }private?User?user=?new?User("大黃",20);public?void?updateUser(User?student){student.setName("小灰");student.setAge(18); }public?void?test(){System.out.println("調用前x的值:"+x);updateValue(x);System.out.println("調用后x的值:"+x);System.out.println("調用前user的值:"+user.toString());updateUser(user);System.out.println("調用后user的值:"+user.toString());}

測試:

Log打印結果如下:

調用前x的值:10 調用后x的值:10 調用前user的值:User{name='大黃,?age=20} 調用后user的值:User{name='小灰,?age=18}

傳遞基本類型的方法(updateValue())流程圖:?

傳遞引用類型的方法(updateUser())流程圖:

這其中也包含著例外,比如String類型和大小不超過127的Long類型,雖然也是引用類型,卻像基本類型一樣不受影響。這是因為它們會先比較常量池維護的值,這涉及VM的內容,今天不做過多討論。

淺拷貝是在按位(bit)拷貝對象,這個對象有著原始對象屬性值的一份精確拷貝。我們結合應用場景分析一下,還是剛才的User類,我們增加一個存放地址的內部類Address,我們需要用戶信息可以被其他module查詢,但是不允許它們被其他module修改,新增代碼如下:

//?這是一個稍微復雜的、支持拷貝的用戶類public?class?User?implements?Cloneable?{ //?……省略上文代碼……private?Address?address;@NonNull@NotNull@Overridepublic?User?clone()?{try{return?(User)super.clone();}catch?(CloneNotSupportedException?e)?{e.printStackTrace();}return?null;}public?class?Address{//?地市public?String?city;//?區縣public?String?county;//?鄉鎮街道public?String?street;}? }

?

//?這是一個更復雜的、支持深拷貝的用戶類public?class?User?implements?Cloneable?{//?……省略上文代碼……@NonNull@NotNull@Overridepublic?User?clone()?{try{User?newUser?=?(User)super.clone();newUser.setName(this.name);newUser.setAddress(this.address.clone());return?newUser;}catch?(CloneNotSupportedException?e)?{e.printStackTrace();}return?null;}public?class?Address?implements?Cloneable{//?……省略上文代碼……@NonNull@NotNull@Overridepublic?Address?clone()?{try{Address?newAddress?=?(Address)super.clone();newAddress.city?=?this.city;newAddress.county?=?this.county;newAddress.street?=?this.street;return?newAddress;}catch?(CloneNotSupportedException?e)?{e.printStackTrace();}return?null;}} }

需要注意的是,上面代碼的深拷貝其實并不徹底,因為徹底的深拷貝幾乎是不可能實現的,那樣不但可能存在引用關系非常復雜的情況,也可能存在引用鏈的某一級上引用了一個沒有實現Cloneable接口的第三方對象的情況。

絕大多數設計模式都是犧牲性能提升開發效率的,原型模式則是為數不多的犧牲開發效率提升性能的設計模式。

?

private?User?user=?new?User("大黃",20);public?void?testNew(){User?user1?=?new?User("小灰",18);}public?void?testClone(){User?user2?=?user.clone();}

通過ASM工具查看bytecode,可以看出二者對棧資源的消耗:?

//?access?flags?0x1public??testNew()V……省略……MAXSTACK??=?4MAXLOCALS?=?2//?access??flags?0x1public??testClone()V……省略……MAXSTACK??=?1MAXLOCALS?=?2 }


@Overridepublic?Object?clone()?{return?new?Intent(this);}


最后我們來總結一下原型模式的核心用途:

1.解決構建復雜對象的資源消耗問題,提升創建對象的效率。

2.保護性拷貝,防止外部對只讀對象進行需修改。



總結

以上是生活随笔為你收集整理的什么是 “原型模式” ?的全部內容,希望文章能夠幫你解決所遇到的問題。

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