1. 程式人生 > >HeadFirst 設計模式閱讀筆記(一)—— strategy

HeadFirst 設計模式閱讀筆記(一)—— strategy

最近正是聖誕假期,利用空閒時間翻翻《HeadFirst 設計模式》。這本書編的很有意思,讀起來並不枯燥。所有設計模式的示例程式碼可以在官方網站免費下載:http://wickedlysmart.com/get-code/,但是我覺得自己寫寫可能更好些。


本系列筆記的目的不是把原書抄一遍,而是隻摘錄一些筆者認為重要的知識點,供以後查閱。希望詳細學習的朋友們不妨去看看原書,確實比一般的技術書輕鬆多了。


第一章主要介紹了“策略模式”,以鴨子類為例講述了這樣一個問題:

  1. 最初設計鴨子這個基類時,我們定義了“呱呱叫”方法,子類“綠頭鴨”繼承鴨子類,一切顯得很完美。
  2. 現在系統升級,多了很多種鴨子,比如“模型鴨子”,它真心不會叫,怎麼辦?
  3. 最簡單的方法是在“模型鴨子”類中重寫“呱呱叫”使之為空。但是很明顯每次有新的不會叫的鴨子出現時我們都要想著重寫這個方法,這顯然是一個“骯髒”的解決方案。
  4. 於是我們想到可以把這個行為抽象成一個介面,每個子類根據自己的需要,如果能叫就實現這個介面。聽上去不錯。
  5. 可是別忘了,大部分鴨子還是呱呱叫的!使用介面使得我們不得不重複相同的程式碼。
  6. 如何在繼承和複用之間找到平衡?
這是一些經驗:
  • 為了複用而使用繼承效果往往不完美
  • 針對介面而不是針對實現程式設計
  • 找出應用中可能變化的行為,把他們獨立出來(封裝)。如此一來系統變得更有彈性。
  • 多用組合少用繼承
最終解決方案:
  1. 把“叫”這一方法抽象成為一個介面。
  2. 不同的叫的方式,比如呱呱叫和吱吱叫被抽象為具體的類,他們實現“叫”介面。
  3. 在基類“鴨子中”如此定義:
      
package headfirst.strategy;
public abstract class Duck {
FlyBehavior flyBehavior;
public Duck() {}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
public void performQuack() {
quackBehavior.quack();
}
}
現在我們不再直接在類中實現“叫”方法(針對實現程式設計),而是定義了一個介面型別的屬性來代表這一方法(針對介面程式設計),如此一來系統就變得靈活多了,因為子類的行為可以在執行時改變!
例:
ModelDuck.java,
public class ModelDuck extends Duck {
public ModelDuck() {
quackBehavior = new 呱呱叫();
}
main:
Duck model = new ModelDuck();
model.performQuack();//現在是呱呱叫
model.setQuackBehavior(new 吱吱叫());
model.performQuack();//現在是吱吱叫!


我們能夠隨時改變模型鴨子的叫聲了。 這就是strategy模式: 定義一個演算法族,分別封裝起來讓他們可以互相替換,此模式使演算法的變化獨立於使用演算法的客戶。 更直觀的一個例子是,在射擊遊戲中,角色可以隨時變化他們手中的槍!setWeapon()...