《Head First 設計模式》:策略模式

驚卻一目發表於2020-05-27

正文

一、定義

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

要點:

  • 策略模式把系統中會變化的部分抽出來封裝。

二、實現步驟

1、建立策略介面

/**
 * 策略介面
 */
public interface Strategy {

    /**
     * 執行策略行為
     */
    public void perform();
}

2、建立策略介面的實現類

(1)策略實現類 A

/**
 * 策略實現類A
 */
public class StrategyImplA implements Strategy {

    /**
     * A策略行為
     */
    @Override
    public void perform() {
        System.out.println("perform A...");
    }
}

(2)策略實現類 B

/**
 * 策略實現類B
 */
public class StrategyImplB implements Strategy {

    /**
     * B策略行為
     */
    @Override
    public void perform() {
        System.out.println("perform B...");
    }
}

3、在使用策略的類中,宣告並使用介面型別的策略變數

/**
 * 策略使用者
 */
public class StrategyUser {
    
    /**
     * 宣告介面型別的策略變數
     */
    private Strategy strategy;
    
    /**
     * 通過構造例項化策略
     */
    public StrategyUser(Strategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 執行策略使用者的行為
     */
    public void doBehavior() {
        // do something...
        
        // 使用策略
        strategy.perform();
        
        // do something...
    }
}

4、通過例項化不同的策略實現類,來改變使用者的行為

public class Test {
    
    public static void main(String[] args) {
        // 使用策略A
        StrategyUser userA = new StrategyUser(new StrategyImplA());
        userA.doBehavior();
        // 使用策略B
        StrategyUser userB = new StrategyUser(new StrategyImplB());
        userB.doBehavior();
    }
}

三、舉個例子

1、背景

Joe 上班的公司做了一套相當成功的模擬鴨子游戲:SimUDuck。遊戲中會出現各種鴨子,鴨子的種類及屬性如下:

  • 種類:綠頭鴨、紅頭鴨、橡皮鴨、誘餌鴨。
  • 屬性:外觀、游泳行為、飛行行為、呱呱叫行為(叫聲)。

不同種類的鴨子所對應的屬性如下:

  • 綠頭鴨:綠頭鴨的外觀、會游泳、會飛行、呱呱叫。
  • 紅頭鴨:紅頭鴨的外觀、會游泳、會飛行、呱呱叫。
  • 橡皮鴨:橡皮鴨的外觀、會游泳(漂浮)、不會飛行、吱吱叫。
  • 誘餌鴨:誘餌鴨的外觀、會游泳(漂浮)、不會飛行、不會叫。

2、要點

  • 由於不同種類的鴨子可能具有不同的飛行行為、呱呱叫行為,因此,可以使用策略模式把這兩種行為抽出來。

3、實現

(1)建立行為介面

/**
 * 飛行行為介面
 */
public interface FlyBehavior {

    public void fly();
}
/**
 * 呱呱叫行為介面
 */
public interface QuackBehavior {

    public void quark();
}

(2)實現行為介面

/**
 * 用翅膀飛行
 */
public class FlyWithWings implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("I'm flying!");
    }
}

/**
 * 不會飛行
 */
public class FlyNoWay implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("I can't flying!");
    }
}
/**
 * 呱呱叫
 */
public class Quack implements QuackBehavior {

    @Override
    public void quark() {
        System.out.println("Quack");
    }
}

/**
 * 吱吱叫
 */
public class Squeak implements QuackBehavior {

    @Override
    public void quark() {
        System.out.println("Squeak");
    }
}

/**
 * 不會叫
 */
public class MuteQuack implements QuackBehavior {

    @Override
    public void quark() {
        System.out.println("<<Silence>>");
    }
}

(3)建立鴨子抽象類,並使用行為介面

/**
 * 鴨子抽象類
 */
public abstract class Duck {
    
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    
    public Duck() {
    }
    
    /**
     * 外觀
     */
    public abstract void display();

    /**
     * 游泳行為
     */
    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
    
    /**
     * 飛行行為
     */
    public void performFly() {
        flyBehavior.fly();
    }
    
    /**
     * 呱呱叫行為
     */
    public void performQuark() {
        quackBehavior.quark();
    }
}

(4)建立鴨子子類,並指定具體的行為實現

/**
 * 綠頭鴨
 */
public class MallardDuck extends Duck {
    
    public MallardDuck() {
        // 指定具體的飛行行為
        flyBehavior = new FlyWithWings();
        // 指定具體的呱呱叫行為
        quackBehavior = new Quack();
    }

    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
}

/**
 * 紅頭鴨
 */
public class RedHeadDuck extends Duck {
    
    public RedHeadDuck() {
        // 指定具體的飛行行為
        flyBehavior = new FlyWithWings();
        // 指定具體的呱呱叫行為
        quackBehavior = new Quack();
    }

    @Override
    public void display() {
        System.out.println("I'm a red head duck");
    }
}

/**
 * 橡皮鴨
 */
public class RubberDuck extends Duck {
    
    public RubberDuck() {
        // 指定具體的飛行行為
        flyBehavior = new FlyNoWay();
        // 指定具體的呱呱叫行為
        quackBehavior = new Squeak();
    }

    @Override
    public void display() {
        System.out.println("I'm a rubber duck");
    }
}

/**
 * 誘餌鴨
 */
public class DecoyDuck extends Duck {
    
    public DecoyDuck() {
        // 指定具體的飛行行為
        flyBehavior = new FlyNoWay();
        // 指定具體的呱呱叫行為
        quackBehavior = new MuteQuack();
    }

    @Override
    public void display() {
        System.out.println("I'm a decoy duck");
    }
}

(5)測試

public class Test {
    
    public static void main(String[] args) {
        // 綠頭鴨
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.performFly();
        mallardDuck.performQuark();
        // 紅頭鴨
        RedHeadDuck redHeadDuck = new RedHeadDuck();
        redHeadDuck.performFly();
        redHeadDuck.performQuark();
        // 橡皮鴨
        RubberDuck rubberDuck = new RubberDuck();
        rubberDuck.performFly();
        rubberDuck.performQuark();
        // 誘餌鴨
        DecoyDuck decoyDuck = new DecoyDuck();
        decoyDuck.performFly();
        decoyDuck.performQuark();
    }
}

相關文章