1. 程式人生 > >策略模式-《Head Firsh 設計模式》第一章

策略模式-《Head Firsh 設計模式》第一章

本文要點:

  • 定義
  • 設計原則一:封裝變換部分
  • 設計原則二:針對介面程式設計,而不是針對實現程式設計。
  • 設計原則三:多用組合,少用繼承。
  • 例項:鴨子與行為

策略模式(Strategy Pattern)

一、定義

策略模式定義了演算法組,分別封裝起來,讓他們之間可以相互替換。此模式讓演算法族的變換獨立於使用該演算法的客戶。

二、設計原則一:封裝變換部分

找出可能變換的部分,將其獨立,使得某些部分的變化不會影響到其他部分。將這些變換的部分(例如行為)分離出來,組成一類。

三、設計原則二:針對介面程式設計,而不是針對實現程式設計。

用行為類去實現行為介面,而不是具體子類去實現行為介面。

針對介面程式設計本質是針對超類程式設計。

關鍵在於利用多型,可以對超類程式設計,在執行時根據具體情況執行行為。

四、例項:鴨子類和行為類

1. 鴨子類

Duke抽象父類,所有的鴨子繼承自父類,在子類裡面實現具體特性,並且設定行為。

public abstract class Duke {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public void setFly(FlyBehavior fly) {
        flyBehavior = fly;
    }
    public
void setQuack(QuackBehavior quack) { quackBehavior = quack; } public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public abstract String getDescription(); } //黑色鴨子(用翅膀飛,會叫) public class BlackDuck extends
Duke{
String color = "black"; public BlackDuck() { flyBehavior = new FlyWithWings(); quackBehavior = new QuackCry(); } public String getDescription() { return color+" "+flyBehavior.getDescription()+" "+quackBehavior.getDescription(); } } //木頭鴨子(不會飛,吱吱叫) public class WoodDuck extends Duke{ String color = "yellow"; public WoodDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new QuackZhiZhi(); } public String getDescription() { return color+" "+flyBehavior.getDescription()+" "+quackBehavior.getDescription(); } }

2.飛行類(行為類-定義中的演算法族)

//飛行介面
public interface FlyBehavior {
    public String getDescription();
    public void fly();
}
//具體飛行行為類:不會飛
public class FlyNoWay implements FlyBehavior{
    public String getDescription() {
        return "fly no way";
    }
    public void fly() {
        System.out.println(getDescription());
    }
}
//用翅膀飛
public class FlyWithWings implements FlyBehavior{
    public String getDescription() {
        return "fly with wings";
    }
    public void fly() {
        System.out.println(getDescription());
    }
}

3.鴨叫類

//鴨叫介面
public interface QuackBehavior {
    public String getDescription();
    public void quack();
}
//正常鴨叫
public class QuackCry implements QuackBehavior{
    public String getDescription() {
        return "quack cry";
    }
    public void quack() {
        System.out.println(getDescription());
    }
}
//吱吱叫
public class QuackZhiZhi implements QuackBehavior{
    public String getDescription() {
        return "quack zhizhi";
    }
    public void quack() {
        System.out.println(getDescription());
    }
}

4.測試

public class testDuck {
    public static void main(String[] args) {
        Duke duke = new BlackDuck();
        System.out.println(duke.getDescription());
        duke.performFly();//飛行
        duke.performQuack();//鴨叫

        duke = new WoodDuck();
        System.out.println(duke.getDescription());
        duke.performFly();
        duke.performQuack();
    }
}

執行程式碼:結果正確

black fly with wings quack cry
fly with wings
quack cry
yellow fly no way quack zhizhi
fly no way
quack zhizhi

5.擴充套件新的行為

我們上面實現了策略模式,現在來擴充套件行為體會一下策略模式的便捷。這裡擴充套件一個火箭推進的行為FlyRocketPowered(),實現`FlyBehavior介面:

public class FlyRocketPowered implements FlyBehavior{
    public String getDescription() {
        return "fly with Rocket Power!!!";
    }
    public void fly() {
        System.out.println(getDescription());
    }
}

給木鴨子改裝火箭推進裝置:

Duke duke = new WoodDuck();
System.out.println(duke.getDescription());
duke.performFly();
duke.performQuack();
duke.setFly(new FlyRocketPowered());//給木鴨子火箭推進器
duke.performFly();

結果:

yellow fly no way quack zhizhi
fly no way
quack zhizhi
fly with Rocket Power!!!

成功的更改為火箭推薦!很方便吧!這就是策略模式更換演算法族(本例中是行為類)的特點,便於擴充套件。

五、設計原則三:多用組合,少用繼承。

1.什麼是組合

像例項中將兩個類組合起來用,這就是組合(Composition)。這種方法和“繼承”的區別在於,鴨子的行為不是繼承而來,而是和適當的行為物件組合而來的。

2.組合的優點

可複用、可擴充套件、可維護

3.繼承提供行為的缺點

  1. 程式碼在多個子類中重複
  2. 執行時行為不容易改變
  3. 難以知道所有行為
  4. 牽一髮而動全身,造成其他子類不想要的改變。