大话设计模式(八 用“策略模式”是一种好策略)
?(續上篇)
?????? 小菜次日來找大鳥,說:“《深入淺出設計模式》的第一章我看完了,它講的是策略模式(Strategy)。『策略模式』定義了算法家族,分別封裝起來,讓它們之間可以互相替換, 此模式讓算法的變化, 不會影響到使用算法的客戶??磥砩虉鍪浙y系統應該考慮用策略模式?”
????? “你問我?你說呢?”大鳥笑道,“商場收銀時如何促銷,用打折還是返利,其實都是一些算法,用工廠來生成算法對象,感覺是不是很怪?而最重要的是這些算法是隨時都可能互相替換的,這就是變化點,而封裝變化點是我們面向對象的一種很重要的思維方式。”
???????策略模式的結構?(源自呂震宇?博客)
???????
??????這個模式涉及到三個角色:
?
- 環境(Context)角色:持有一個Strategy類的引用。
- 抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
- 具體策略(ConcreteStrategy)角色:包裝了相關的算法或行為。
??????“我明白了,”小菜說,“我昨天寫的CashSuper就是抽象策略,而正常收費CashNormal、打折收費CashRebate和返利收費CashReturn就是三個具體策略,也就是策略模式中說的具體算法,對吧?”
??????“是的,那么關鍵就在于Context以及客戶端程序如何寫了?去查查資料,研究后把代碼寫出來給我看?!贝篪B鼓勵道。
????? “好的,我一定很快寫出來給你看!”小菜很興奮。
????????過一小時后,小菜給出商場收銀程序的第四份作業。
CashContext類代碼如下: //收費策略Contextclass CashContext{//聲明一個現金收費父類對象private CashSuper cs;//設置策略行為,參數為具體的現金收費子類(正常,打折或返利)public void setBehavior(CashSuper csuper){this.cs = csuper;}//得到現金促銷計算結果(利用了多態機制,不同的策略行為導致不同的結果)public double GetResult(double money){return cs.acceptCash(money);}}
?
客戶端主要代碼如下:
double total = 0.0d;//用于總計private void btnOk_Click(object sender, EventArgs e){CashContext cc = new CashContext();switch (cbxType.SelectedItem.ToString()){case "正常收費":cc.setBehavior(new CashNormal());break;case "滿300返100":cc.setBehavior(new CashReturn("300","100"));break;case "打8折":cc.setBehavior(new CashRebate("0.8"));break;}double totalPrices = 0d;totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));total = total + totalPrices;lbxList.Items.Add("單價:" + txtPrice.Text + " 數量:" + txtNum.Text + " "+cbxType.SelectedItem+ " 合計:" + totalPrices.ToString());lblResult.Text = total.ToString();}
實現的界面同之前一樣(可點擊使用)
?????? “大鳥,我用策略模式是實現了,但有些疑問,用了策略模式,則把分支判斷又放回到客戶端來了,這等于要改變需求算法時,還是要去更改客戶端的程序呀?”
?????? “問得好,如果不是因為前面有工廠的例子,再來通過你的思考寫出的這個策略模式的程序,你就問不出這樣的問題的?!贝篪B很開心,繼續講道,“最初的策略模式是有缺點的,客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。這就意味著客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用于客戶端知道所有的算法或行為的情況。”
??????? “那還不如工廠模式好用,至少要增加促銷或改進打折額度時,不用去大改界面,而現在,界面程序要承擔的責任還是太大。沒有體現你說的封裝變化點的作用呀?!毙〔艘蓡柖喽唷?br /> ?????? “就目前而言,的確是這樣,這樣的程序確實還是不夠完善,要改的地方還很多?!贝篪B說道,“不過正所謂病毒時間長了會有變種,殺毒軟件本身也會隨著病毒的變化而升級改良,如果我們對策略模式做一些改進,引入一些新的技術處理方式,就可以避免現在的這種耦合了。小菜,又有新的東西要學了,好好加油呀!”
??????“大鳥,謝謝你,,你總是讓我帶著問題去思考,而不是直接說答案,我覺得這樣學習進步很快,也不覺得設計模式很難了?!?
????? “,用不著這么客氣,我只是覺得,沒有人是天生就牛X的,有一些所謂的技術牛人總會在人面前說什么,‘你連這都不懂’,‘這還不簡單了,你夠笨的’等等說詞。給人感覺他非常聰明,天生就會的樣子,其實他在之前也不知走過多少彎路,犯過多少錯,或許他之前也被更早的牛人羞辱過,所以再繼續把羞辱傳給后人?!贝篪B有些激動。
?????? 小菜小心的說道:“大鳥,你是不是也曾經被人羞……”
?????? “哈哈,馬云曾說過,男人的胸懷是被冤枉撐大的!天天在這行當里混,閱人無數,被羞辱也是正常的事了。問題在于是不是頭腦清醒,自己不能放棄呀。所以我希望能真正的幫助初學者成長,而不是去顯示牛氣充當狂人。小菜,記住,學習一定是一個自己感悟的過程,而程序員的感悟就是自己寫程序做項目,通過實踐再學習,最終升華為牛人。”
??????“嗯,我記住了,不過到底如何改良策略模式呢?”
???????大鳥微笑不語。
(待續)
本文相關源代碼
出處:http://www.cnblogs.com/cj723/archive/2007/03/21/682479.html
總結
以上是生活随笔為你收集整理的大话设计模式(八 用“策略模式”是一种好策略)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大话设计模式(七 工厂不好用了?)
- 下一篇: 大话设计模式(九 反射——程序员的快乐!