策略模式也是一種好用的模式,可以封裝並獨立不同的演算法,符合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/