說明:以下內容是學習Head First後自行整理的筆記。內容和程序均來自於該書
策略模式:定義了算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓算法的變化獨立於使用算法的客戶。
概念理解起來生硬,下面用一個鴨子的例子說明。
有一個模擬鴨子的遊戲。遊戲中有各種各樣的鴨子,它們可以游泳,呱呱叫。按照之前的設計一般是這樣的:有一個鴨子的超類Duck,有swim、quack的方法,然後不同的鴨子類去繼承它。
這個時候多了一個需求,要讓鴨子會飛,很自然你會在Duck裏面去加一個fly方法。
仔細想一想這種設計思路,是不是會存在問題。
1、如果你在Duck裏對fly等方法做了實現,這個時候會出現問題,那就是並不是所有的鴨子都是會飛的,比如只有野鴨子會飛,橡皮鴨並不會飛。
2、當然你會說我會把實現放到子類中,超類並不做實現。那麼另一個問題自然會出現,那就是如果野鴨子跟水鴨子都是會飛的,而且都是一樣的飛法,那fly這個方法不就會被寫了兩次甚至跟多,這樣是不利於維護的。而且如果遊戲中有另一個類:鵝,它也是會飛的,那就更加麻煩了。
所以這個時候策略模式就發揮作用了
下圖是設計的思路
下面是代碼
Duck.java
package bean; public abstract class Duck { public Duck(){}; FlyBehavior flyBehavior; QuackBehavior quackBehavior; public FlyBehavior getFlyBehavior() { return flyBehavior; } public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public QuackBehavior getQuackBehavior() { return quackBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } public void swim(){ System.out.println(); } public void fly(){ flyBehavior.fly(); } public void quack(){ quackBehavior.quack(); } }
FlyBehavior.java
package bean; public interface FlyBehavior { public void fly(); }
FlyWithWings.java
package bean; public class FlyWithWings implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("I fly with wing!"); } }
FlyNoWay.java
package bean; public class FlyNoWay implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println("I can't fly"); } }
QuackBehavior.java
package bean; public interface QuackBehavior { public void quack(); }
QuackGaGa.java
package bean; public class QuackGaGa implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.out.println("ga ga"); } }
QuackNoWay.java
package bean; public class QuackNoWay implements QuackBehavior { @Override public void quack() { // TODO Auto-generated method stub System.out.println("I can't quack"); } }
CleverDuck,java
package bean; public class CleverDuck extends Duck { public CleverDuck(){ this.flyBehavior = new FlyWithWings(); this.quackBehavior = new QuackGaGa(); } }
StupidDuck.java
package bean; public class StupidDuck extends Duck { public StupidDuck(){ this.flyBehavior = new FlyNoWay(); this.quackBehavior = new QuackNoWay(); } }
設計原則:
1、針對接口編程,而不是針對實現編程(這個很好理解)
2、多用組合,少用繼承。(如本例中,鴨子的行爲不是靠繼承得來的,而是通過行爲對象的“組合”得來的,這讓程序更加的靈活)