加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

理解不變模式-Immutable Pattern<一>

发布时间:2020-12-17 01:03:44 所属栏目:安全 来源:网络整理
导读:題記:上邪?我欲與君相知?長命無絕衰?山無陵?江水為竭?冬雷陣陣?夏雨雪?天地合?乃敢與君絕 ? 從String說起: 用Java或C#時,如果一個字串是頻繁變化的,是不建議把該變數設為String類型的,而建議為StringBuilder,經過N次變化得到最終的字串後,再把StringB

題記:上邪?我欲與君相知?長命無絕衰?山無陵?江水為竭?冬雷陣陣?夏雨雪?天地合?乃敢與君絕

?

從String說起:

用Java或C#時,如果一個字串是頻繁變化的,是不建議把該變數設為String類型的,而建議為StringBuilder,經過N次變化得到最終的字串後,再把StringBuilder轉化為String交給某個方法去處理。

不變模式會告訴我們,這是為什麼?

備註:

我學習設計模式時基本都參考閻巨集的《Java與模式》一書,該書中講述不變模式舉String這個例子時,若字串頻繁變化時建議使用StringBuffer,我原來用C#寫代碼時習慣用StringBuilder,.netframework只保證StringBuilder的公共Static成員是執行緒安全的。於是我去查看Java中StringBuilder的原碼發現該類的注釋中有這麼一句:

Wherepossible,it isrecommended that this class be used in preference to StringBufferas it will befaster under most implementations.

請注意?“wherepossible”,的意思是:在單執行緒情況下。而StringBuffer是執行緒安全的。

?

不變模式的概念:

?

一個物件如果可以改變自身的狀態,我們說它是可變的;如果一個物件的狀態自創建起便不可改變,我們說它是不可變的。

不變模式只涉及到一個類,這個類的內部狀態創建以後,在整個生命週期都不會發生變化,這樣的類叫做不變類,這種使用不變類的做法叫做不變模式。不變模式只有一個類,所以不需要類圖來表示。

備註:什麼是內部狀態?

在書上看,第一眼挺暈的,因為搞學術的都有這“毛病”,喜歡把簡單的東西說的很複雜,你看那些博士論文,還有一些很牛B的碩士論文就會發現這個問題。我只所以把“毛病”加引號是因為我不全盤否定這種做法,雖然他對初學者及搞應用的人來講會造成一定的障礙,但它對理論的發展卻很重要,因為我們理解這個概念以後,討論起來就會更加清晰,就像無論我們學什麼,講什麼第一步總是要先把概念講清楚,理解清楚。如果缺了這一步,費半天勁會發現不知道自己在幹什麼,這個太可怕了。

言歸正傳,所謂內部狀態,就是這個類的屬性,完了。就像WebService,一聽好神奇啊,你去看書,那理論一套一套的好幾章,說白了就是:基於Web的API,完了。

怎麼讓它不變:

使用不變類的做法就是不變模式,所謂不變類就是它的整個生命週期裡它的狀態就不會改變,那怎樣讓它的狀態(屬性)不會發生變化呢?當我們把概念講到這裡的時候,我想我們基本都會把它寫出來了:把屬性設為私有,只給Geter不給Setter就OK了。Yes!給個例子先:

?

public?class?PartySchool{

????private?String?appearance;

?

????public?StringgetAppearance() {

???????return?appearance;

????}

????public?PartySchool(Stringappearance)

????{

???????this.appearance?= appearance;

????}

}

CodeIP-1

當用戶端調用的時候給予初始值:

PartySchool ps =newPartySchool(“handsome”);

那麼在PartySchool的整個生命週期裡一直都handsome,是不可變的。

特殊情況:

我家養了一條狗叫毛毛,給毛毛建個類先:

public?class?Dog{

????private?String?name;

?

????public?StringgetName() {

???????return?name;

????}

?

????public?void?setName(String name) {

???????this.name?= name;

????}

????public?Dog(Stringname)

????{

???????this.name?= name;

????}

}

CodeIP-2

顯然,我們家毛毛的名字是可以改的,比如我不叫它毛毛了給它取個英文名字叫Douglas。

順便把PartySchool這個類也修改下:

public?class?PartySchool{

????private?String?appearance;

????private?Dog?dog;

????public?StringgetAppearance() {

???????return?appearance;

????}

????public?DoggetDog() {

???????return?dog;

????}

?

????public?PartySchool(Stringappearance,Dog dog)

????{

???????this.appearance?= appearance;

???????this.dog?=dog;

????}

}

CodeIP-3

我想看到這個類會隱隱有種不詳的預感,寫個測試驗證一下:

public?static?void?main(String[] args) {

???????Dogdog =?new?Dog("maomao");

???????PartySchoolps =?new?PartySchool("handsome",dog);

???????System.out.println(ps.getAppearance());

???????System.out.println(ps.getDog().getName());

???????System.out.println("-----------------Changed--------------------");

???????dog.setName("Douglas");

???????System.out.println(ps.getAppearance());

???????System.out.println(ps.getDog().getName());

????}

CodeIP-4

悲劇的結果:

handsome

maomao

-----------------Changed--------------------

handsome

Douglas

悲劇發生了,因為不變類裡出現了可變的不和諧分子。如何把它和諧掉呢?偉大的程式師是不需要維穩經費的,我們只需要改掉一行代碼就OK了。

把PartySchool的構造函數改為:

????public?PartySchool(Stringappearance,Dog dog)

????{

???????this.appearance?= appearance;

???????DogdogClone =?new?Dog(dog.getName());

???????this.dog?=dogClone;

????}

CodeIP-5

同樣的測試用例測試結果:

handsome

maomao

-----------------Changed--------------------

handsome

maomao

好!歌舞昇平,我家毛毛還叫毛毛。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读