策略模式也是一種好用的模式,可以封裝並獨立不同的演算法,符合SRP單一職責原則跟OCP開放關閉原則。
透過composition的方式,將演算法放入物件中,並且是宣告為interface,才能寫更多concreteStrategy,保留很大的彈性。

我們有很多種鴨子,所以宣告一個Abstract Duck,
確定鴨子都會swim()跟display()(一定要display些什麼,所以宣告為abstract,必須override)
package com.example.designpattern.behavior.strategy;
public abstract class Duck {
    public Duck(){};
    private FlyBehavior flyBehavior;       // 這邊是interface
    private QuackBehavior quackBehavior;   // 這邊是interface
    public abstract void display();
    public void swim() {
        System.out.println("I can swim.");
    }
    protected void performFly() {
        flyBehavior.fly();
    }
    protected void performQuack() {
        quackBehavior.quack();
    }
    public void setFlyBehavior(FlyBehavior flyBehavior) {  // 這裡有setter,可以把不同演算法set進物件
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {  // 這裡有setter,可以把不同演算法set進物件
        this.quackBehavior = quackBehavior;
    }
}
public interface FlyBehavior {
    void fly();
}
public interface QuackBehavior {
    void quack();
}
public class GreenDuck extends Duck{
    @Override
    public void display() {
        System.out.println("I am green.");
    }
}
public class FlyWithWings implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("fly with wings");
    }
}
public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("quack quack quack");
    }
}
最後來建立鴨子物件吧,並給她適合的fly跟quack演算法
public class DuckClient {
    public static void main(String[] args) {
        Duck duck = new GreenDuck();
        duck.setFlyBehavior(new FlyWithWings()); // strategy pattern
        duck.setQuackBehavior(new Quack());      // strategy pattern
        duck.swim();
        duck.performFly();
        duck.performQuack();
        duck.display();
    }
}
https://refactoring.guru/design-patterns/strategy
https://www.oreilly.com/library/view/head-first-design/0596007124/