--- tags: Behavioral Patterns --- # 策略模式 Strategy 疑問? Strategy 跟 Context 之間的關係是 aggregation? > [name=毓昇] 要解決一個class在不同種類或品種時會有不同行為(如:鴨子有些會飛有些不會),最簡單的做法就是把那個行為拉出來用Interface解決,但如果種類越來越多,這可能會造成維護困難。 ![](https://i.imgur.com/pKHRiTK.png) 使用Interface的結構圖,每個鴨子都有不同叫法跟會不會飛的行為,每次增加一個鴨子種類的class就要去實作兩個介面。 策略模式設計守則: 1. 把程式中可能變動的部份獨立出來 2. 寫程式是針對介面寫, 不是針對實作方式寫 3. 多用合成, 少用繼承 解法: 當宣告一個鴨子時,我們可以直接**合成**一個鴨子的叫法以及能不能飛(把要使用的介面塞進去class)。 更改過後產生的新圖 ![](https://i.imgur.com/traAB0c.png) 總體架構圖 ![](https://i.imgur.com/A6JwMI6.png) **程式說明** ```javascript public abstract class Duck { Flyable flyAble; Quackable quackAble; public abstract void display(); public void performFly(){ if(flyAble != null) flyAble.fly(); } public void performQuack() { if(quackAble != null) quackAble.quack(); } //設定哪種叫法或能不能飛行 public void setFlyable(Flyable fly){ flyAble = fly; } public void setQuackable(Quackable quack){ quackAble = quack; } } public class SuperFly implements Flyable { public void fly(){ System.out.println("I'm super flying!!"); } } public class SuperQuack implements Quackable { public void quack(){ System.out.println("I'm super quacking!!"); } } public class SuperDuck extends Duck { public void display(){ System.out.println("I'm super duck!!"); } } public class DuckTest { pubilc static void main(String[] args){ Duck duck = new SuperDuck(); // 指定這隻鴨怎麼飛 duck.setFlyable(new SuperFly()); // 指定這隻鴨怎麼叫 duck.setQuackable(new SuperQuack()); duck.performFly(); duck.performQuack(); } } ``` > [name=閔致]