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

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

 

從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

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值