設計模式——策略模式

《Head First設計模式》筆記整理...歡迎交流...算法

定義

定義了算法簇,分別封裝起來,讓他們之間能夠 相互替換,此模式讓算法的變化獨立於使用算法的客戶。

這裏稍微提醒一下,策略模式是咱們學習的第一個模式,理解它仍是很是重要的。這個模式跟後面講到的 模板模式 有些類似的地方,我在學習的時候,看到模板模式已經忘記什麼是策略模式了,看的一臉懵逼。不過不要緊,後面我會針對這兩個進行整理,這裏要記住的是,策略模式封裝了一組能夠互換的算法簇,是針對接口編程的。編程

OO原則

  • 封裝變化
  • 多用組合,少用繼承
  • 針對接口編程,而不是針對實現編程

封裝變化

爲何要封裝變化?先來看下面的例子。設計模式

dock類是全部鴨子的超類,其中,飛行(fly)行爲和呱呱叫(quack)行爲會隨着鴨子的不一樣而改變。若是咱們不區分變化,將全部的行爲定義在超類裏。如圖:學習

圖片描述

顯而易見的,這種設計會致使測試

  • 改變牽一髮而動全身
  • 不利於複用,不利於維護
  • 代碼在多個子類中重複
  • 很難知道鴨子的所有行爲
  • 運行時代碼不容易改變

爲了便於之後能夠輕易地改動和擴展此部分,而不會影響不須要改變的其它部分,咱們把變化的部分取出並封裝起來。spa

圖片描述

使用繼承如何?設計一個flyable接口和一個quackable接口。設計

圖片描述

哇,一堆重複的代碼,並且代碼難以複用。甚至在會飛的鴨子中,飛行的動做也多是變幻無窮的。若是咱們想要更加彈性一點,在運行時也能夠動態地選擇行爲,該怎麼辦呢?code

針對接口編程

針對接口編程,而不是針對實現編程。這裏所謂的「接口」有多個含義,接口能夠是一個「概念」。」針對接口變成「,關鍵就在於「多態」,能夠更明確地說,變量的聲明類型應該是超類型。這也意味着,聲明類是沒必要理會之後執行時的真正的對象類型。orm

圖片描述

如此,鴨子的行爲被放在分開的類中,此類專門提供行爲的接口實現。
這樣,鴨子類就再也不須要知道行爲的實現細節。對象

多用組合,少用繼承

當你講兩個類結合起來使用,就是組合。如圖本列,將飛行行爲和呱呱叫行爲委託給FlyBehavior和QuackBehavior代爲處理。組合創建系統有很大的彈性,不只可將算法簇封裝成類,更能夠在運行時動態地改變行爲,只要組合的行爲對象符合正確的接口便可。

代碼演示

publick abstract class Duck {
    //爲行爲接口類型聲明兩個引用變量,全部鴨子子類都繼承它們
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public Duck() {
    }
    
    publick abstract void display();
    
    public void performFly() {
        flyBehavior.fly(); //委託行爲給類
    }
    
    public void performQuack() {
        quackBehavior.quack(); //委託行爲給類
    }
    
    public viod  setFlyBehavior(FlyBehavior fb) {
        flyBehavior = fb; //動態設定飛行行爲
    }
    
    public viod  setQuackBehavior(QuackBehavior qb) {
        quackBehavior = qb; //動態設定呱呱叫行爲
    }
}

-----------------------------------------------------------

public interface FlyBehavior {
    public void fly();
}

public class FlyWithWings implements FlyBehavior {
    public viod fly() {
        System.out.printIn("I'm flying!");
    }
}

public class FlyNoWay implements FlyBehavior {
    public void fly {
        System.out.printIn("I can't fly!");
    }
}

-----------------------------------------------------------

public class QuackBehavior {
    public void quack();
}

public class Quack implements QuackBehavior {
    public void quack() {
        //此處省略
    }
}

public class MuteQuack implements QuackBehavior {
    public void quack() {
        //此處省略
    }
}

public class Squack implements QuackBehavior {
    public void quack() {
        //此處省略
    }
}
//製造一個新的鴨子類型:模型鴨

public class ModelDuck extends Duck {
    public ModelDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }
    
    public viod display () {
        System.out.printIn("I'm a model duck");
    }
    
}

--------------------------------------------------------
//新建一個新的FlyBehavior類型

public class FlyRocketPowered implements FlyBehavior{
    public viod fly() {
        System.out.printIn("I'm flying with a rocket!");
    }
}

最後,來看看一個簡單的測試

Duck model = new ModelDuck();
model.performFly(); // i can't fly!
model.setFlyBehavior(new FlyRocketPowered()); //動態改變行爲
model.performFly(); // I'm flying with a rocket!

若是咱們再也不把鴨子的行爲看作「一組行爲」,而是想成是「一簇算法」,將這些算法抽離並封裝起來,委託給對象,經過組合實現運行時算法互換,這就是策略模式。

好了,你以爲個人整理如何呢?若是有什麼理解不對的地方,或者你有更好的想法歡迎交流。

相關文章
相關標籤/搜索