设计模式 -- 策略模式
Head First 里面对策略模式的描述:
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
例子:
我们要制作一堆游戏里面的猫猫形象,里面的猫暂时主要
有2个技能:跑与叫,但不是每一只猫的这两种技能都是好的,有的不会,有的差,有的好;
共同技能:游泳;
当然它们各自有自己的形态;
于是乎有了以下的类图:
代码实现如下:
RunBehaviour 抽象出跑的行为接口
1 package strategy.run; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public interface RunBehaviour 7 { 8 void run(); 9 }
NoRunBehaviour 是 RunBehaviour 的算法族里面的一员
1 package strategy.run; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public class NoRunBehaviour implements RunBehaviour 7 { 8 @Override 9 public void run() 10 { 11 System.out.println("~~~ no run ~~~"); 12 } 13 }
BadRunBehaviour 也是 RunBehaviour 的算法族里面的一员
1 package strategy.run; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public class BadRunBehaviour implements RunBehaviour 7 { 8 @Override 9 public void run() 10 { 11 System.out.println("~~~ bad run ~~~"); 12 } 13 }
GoodRunBehaviour 也是 RunBehaviour 的算法族里面的一员
1 package strategy.run; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public class GoodRunBehaviour implements RunBehaviour 7 { 8 @Override 9 public void run() 10 { 11 System.out.println("~~~ good run ~~~"); 12 } 13 }
好了,上面完成了run的算法族,就该轮到meow了,同样的道理,抽象出meow 接口
1 package strategy.meow; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public interface MeowBehaviour 7 { 8 void meow(); 9 }
NoMeowBehaviour
1 package strategy.meow; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public class NoMeowBehaviour implements MeowBehaviour 7 { 8 @Override 9 public void meow() 10 { 11 System.out.println("~~~ no meow ~~~"); 12 } 13 }
BadMeowBehaviour
1 package strategy.meow; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public class BadMeowBehaviour implements MeowBehaviour 7 { 8 @Override 9 public void meow() 10 { 11 System.out.println("~~~ bad meow ~~~"); 12 } 13 }
GoodMeowBehaviour
1 package strategy.meow; 2 3 /** 4 * Created by chenjiayin on 2017/3/17. 5 */ 6 public class GoodMeowBehaviour implements MeowBehaviour 7 { 8 @Override 9 public void meow() 10 { 11 System.out.println("~~~ good meow ~~~"); 12 } 13 }
到此阶段,算法族已经封装完毕,是时候来使用它们了。抽象出Cat 的抽象类
1 package strategy.cat; 2 3 import strategy.run.RunBehaviour; 4 import strategy.meow.MeowBehaviour; 5 6 /** 7 * Created by chenjiayin on 2017/3/17. 8 */ 9 public abstract class AbstractCat 10 { 11 RunBehaviour runBehaviour; 12 MeowBehaviour meowBehaviour; 13 14 public void fly() 15 { 16 runBehaviour.run(); 17 } 18 19 public void quack() 20 { 21 meowBehaviour.meow(); 22 } 23 24 public void swim() 25 { 26 System.out.println("~~~ swim ~~~"); 27 } 28 29 public abstract void diplay(); 30 }
肥猫(FatCat),由于太胖了,不会跑,只会叫
1 package strategy.cat; 2 3 import strategy.run.NoRunBehaviour; 4 import strategy.meow.GoodMeowBehaviour; 5 6 /** 7 * Created by chenjiayin on 2017/3/17. 8 */ 9 public class FatCat extends AbstractCat 10 { 11 public FatCat() 12 { 13 runBehaviour = new NoRunBehaviour(); 14 meowBehaviour = new GoodMeowBehaviour(); 15 } 16 17 @Override 18 public void diplay() 19 { 20 System.out.println("*** fat cat ***"); 21 } 22 }
瘦猫(ThinCat)
1 package strategy.cat; 2 3 import strategy.run.GoodRunBehaviour; 4 import strategy.meow.BadMeowBehaviour; 5 6 /** 7 * Created by chenjiayin on 2017/3/17. 8 */ 9 public class ThinCat extends AbstractCat 10 { 11 public ThinCat() 12 { 13 runBehaviour = new GoodRunBehaviour(); 14 meowBehaviour = new BadMeowBehaviour(); 15 } 16 17 @Override 18 public void diplay() 19 { 20 System.out.println("*** thin cat ***"); 21 } 22 }
最后,我们来使用下面的方法来验证一下我们的代码!
1 package strategy; 2 3 import strategy.cat.AbstractCat; 4 import strategy.cat.FatCat; 5 import strategy.cat.ThinCat; 6 7 /** 8 * Created by chenjiayin on 2017/3/17. 9 */ 10 public class StrategyMain 11 { 12 public static void main(String[] args) 13 { 14 AbstractCat fatDuck = new FatCat(); 15 AbstractCat thinDuck = new ThinCat(); 16 17 fatDuck.diplay(); 18 fatDuck.quack(); 19 fatDuck.fly(); 20 fatDuck.swim(); 21 22 System.out.println(); 23 24 thinDuck.diplay(); 25 thinDuck.quack(); 26 thinDuck.fly(); 27 thinDuck.swim(); 28 } 29 }
输出:
*** fat cat *** ~~~ good meow ~~~ ~~~ no run ~~~ ~~~ swim ~~~ *** thin cat *** ~~~ bad meow ~~~ ~~~ good run ~~~ ~~~ swim ~~~
总结:
其实策略模式就有点类似于做象限轴。
上面的例子当中就是一个二维的象限轴,RunBehaviour 就是X轴,MeowBehaviour 就是Y轴,而FatCat 与ThinCat 就是一个具体在二维空间上的描点。
所以,随着象限轴的增加,可组合而成的点(具体的类)也会越来越多,但是我们只需要很少量的改动,就可以为我们带来大量的扩展。