对于很多的程序而言,我们为他设计一个很好的策略,那个什么什么是策略模式呢?
举个例子吧:对于一个超市来说,他在不同的时间段会有不同的销售策略啊,比如消费到200元的 400元的 700元的给予打折,会员的等等,这些打折什么的其实就是一个计算方法的不同罢了。
当然了,我们的HeadFirst不是针对这个例子实现的,他是说一个鸭子的实现,鸭子的一些操作可能会变化,如鸭子有会飞的,不会飞的,会叫的不会叫的,会游泳的不会游泳,那么怎么设计呢,我们需要定义这三个接口,让我们来面向接口编程吧。
package com.ownwell.strategy.interfaces;
/**
* 飞动作
* @author ownwell
*
*
*/
public interface FlyBehavior {
void fly();
}


1 package com.ownwell.strategy.interfaces; 2 3 /** 4 * 鸣叫动作 5 * @author ownwell 6 * 7 */ 8 public interface QuakBehavior { 9 void quack(); 10 }


package com.ownwell.strategy.interfaces; /** * 游泳动作 * @author ownwell * */ public interface SwingBehavior { void swing(); }
上面的三个接口只是定义了一些函数(未实现), 那么让我们来实现这些具体的一些操作吧:


1 package com.ownwell.strategy.implement; 2 3 import com.ownwell.strategy.interfaces.FlyBehavior; 4 5 /** 6 * 用翅膀飛 7 * @author Administrator 8 * 9 */ 10 public class FlyWithWings implements FlyBehavior{ 11 12 public void fly() { 13 System.out.println("I can fly with my wings"); 14 15 } 16 17 }


1 package com.ownwell.strategy.implement; 2 3 import com.ownwell.strategy.interfaces.FlyBehavior; 4 5 /** 6 * 俺不會飛啊 7 * @author Administrator 8 * 9 */ 10 public class NoWayFly implements FlyBehavior { 11 12 @Override 13 public void fly() { 14 System.out.println("I cannot fly"); 15 16 } 17 }
package com.ownwell.strategy.implement; import com.ownwell.strategy.interfaces.SwingBehavior; /** * 我是個旱鴨子不怎麼會游泳 * @author Administrator * */ public class NoWaySwing implements SwingBehavior { @Override public void swing() { System.out.println("I cannot swing"); } }


1 package com.ownwell.strategy.implement; 2 3 import com.ownwell.strategy.interfaces.SwingBehavior; 4 /** 5 * 用腳蹼游泳 6 * @author Administrator 7 * 8 */ 9 public class SwingWithWebbed implements SwingBehavior { 10 11 @Override 12 public void swing() { 13 System.out.println("I can swing with my webbeds"); 14 15 } 16 17 }
这样就可以对飞和游泳来分别處理了,當然了你也可以組合了,現在我們要先定義一個抽象的鴨子類啊.


1 package com.ownwell.strategy; 2 3 import com.ownwell.strategy.interfaces.FlyBehavior; 4 import com.ownwell.strategy.interfaces.QuakBehavior; 5 import com.ownwell.strategy.interfaces.SwingBehavior; 6 7 public abstract class IDuck { 8 protected FlyBehavior flyBehavior = null; 9 protected QuakBehavior quakBehavior = null; 10 protected SwingBehavior swingBehavior =null; 11 public IDuck() 12 { 13 } 14 public abstract void display(); 15 16 public void flyPerform(){ 17 if (flyBehavior != null) { 18 19 flyBehavior.fly(); 20 } 21 } 22 public void quakPerform(){ 23 if(quakBehavior != null){ 24 quakBehavior.quack(); 25 } 26 } 27 public void swingPerform(){ 28 if(swingBehavior != null) 29 { 30 31 swingBehavior.swing(); 32 } 33 } 34 35 public void setFlyBehavior(FlyBehavior flyBehavior) { 36 this.flyBehavior = flyBehavior; 37 } 38 39 public void setQuakBehavior(QuakBehavior quakBehavior) { 40 this.quakBehavior = quakBehavior; 41 } 42 43 public void setSwingBehavior(SwingBehavior swingBehavior) { 44 this.swingBehavior = swingBehavior; 45 } 46 47 }
然而這是最好的么?
我們現在要定義一個會叫但不會游泳的鴨子,怎麼辦啊? 不是,是我們想定義個一個會游泳但不叫的鴨子。 怎麼辦 ????
現在我們來提示下:在那個IDuck裏面的get和set方法我們沒用到啊,對了就是可以通過外面傳遞鴨子的行為類:


1 package com.ownwell.juint; 2 3 import static org.junit.Assert.*; 4 5 import org.junit.Test; 6 7 import com.ownwell.strategy.IDuck; 8 import com.ownwell.strategy.duckImp.DuckModel; 9 import com.ownwell.strategy.implement.FlyWithWings; 10 import com.ownwell.strategy.implement.NoWayFly; 11 import com.ownwell.strategy.implement.NoWaySwing; 12 import com.ownwell.strategy.implement.SwingWithWebbed; 13 import com.ownwell.strategy.interfaces.FlyBehavior; 14 import com.ownwell.strategy.interfaces.SwingBehavior; 15 16 public class TestDuck { 17 18 @Test 19 public void test() { 20 IDuck duck = new IDuck() { 21 public void display() { 22 // TODO Auto-generated method stub 23 24 } 25 }; 26 27 FlyBehavior flyWithWings = new FlyWithWings(); 28 FlyBehavior noWayFly = new NoWayFly(); 29 SwingBehavior swingWithWebbed = new SwingWithWebbed(); 30 SwingBehavior noWaySwing = new NoWaySwing(); 31 32 duck.setFlyBehavior(flyWithWings); 33 duck.setSwingBehavior(noWaySwing); 34 35 36 duck.swingPerform(); 37 duck.flyPerform(); 38 39 } 40 41 }
這四個是可以直接組合的,而不必每次都去實現IDUCK這裡只是對IDuck接口去實現它就OK了。
現在我們比較一下是繼承了IDuck的DuckModel好還是我們自己對接口操作好呢?
其實我們設計的一個原則就是少用繼承,而用組合。
繼承就是子類實現父類的一些操作,而組合則是將不同的操作通過組合得到一個好的拓展.。