Java设计模式中的策略模式(Strategy Patten)定义了一组算法,将每个算法都封装起来,并且可使它们之间可以相互替换,在客户端调用它们时可以互不影响。
策略模式主要由三个角色组成
1、抽象策略角色:通常是一个接口或抽象类实现,我们的具体策略类就是继承或实现这个抽象角色。
2、具体策略角色:我们在这些类中写策略和算法,继承或实现抽象策略角色。
3、环境角色:环境角色中拥有一个抽象策略角色的引用,供客户端调用,该角色把客户端跟策略类的实现分离。
从上面的三个策略模式的角色中,我们就大概可以知道策略模式的编写步骤,这里以实现简单的四则运算为例。
1、定义抽象策略角色,也就是定义一个公共的抽象类(也可以是接口)
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 *定义抽象策略角色 6 */ 7 public abstract class Strategy { 8 //定义抽象策略的方法 9 public abstract int strategy(int a,int b); 10 11 }
2、编写策略类,该类实现上面定义的抽象类
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * AddStrategy 6 */ 7 public class AddStrategy extends Strategy { 8 //定义实现加法的策略方法 9 public int strategy(int a, int b) 10 { 11 return a+b; 12 } 13 14 }
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * SubStrategy 6 */ 7 public class SubStrategy extends Strategy { 8 //定义减法的策略方法 9 public int strategy(int a, int b) 10 { 11 return a-b; 12 } 13 14 }
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * MultiplyStrategy 6 */ 7 public class MultiplyStrategy extends Strategy { 8 //定义乘法的策略方法 9 public int strategy(int a,int b) 10 { 11 return a*b; 12 } 13 }
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * DivStrategy 6 */ 7 public class DivStrategy extends Strategy { 8 //定义除法的策略方法,这里为了简单就不考虑除数为零的情况了 9 public int strategy(int a,int b) 10 { 11 return a/b; 12 } 13 }
3、编写环境角色,其中持有一个抽象策略类的引用
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * Context 6 */ 7 public class Context { 8 //持有抽象策略角色的引用,用于客户端调用 9 private Strategy strategy; 10 //获得策略类 11 public Strategy getStrategy() { 12 return strategy; 13 } 14 //设置所需策略 15 public void setStrategy(Strategy strategy) { 16 this.strategy = strategy; 17 18 } 19 //根据设置的策略类返回对应的结果 20 public int getResult(int a,int b) 21 { 22 return strategy.strategy(a, b); 23 } 24 25 }
4、编写客户端
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * Client 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 10 Context context = new Context(); 11 12 int result; 13 14 context.setStrategy(new SubStrategy()); 15 16 result = context.getResult(9, 3); 17 18 System.out.println("sub: "+result); 19 20 context.setStrategy(new AddStrategy()); 21 22 result =context.getResult(9, 3); 23 24 System.out.println("add: "+result); 25 26 context.setStrategy(new DivStrategy()); 27 28 result = context.getResult(9, 3); 29 30 System.out.println("div: "+result); 31 32 context.setStrategy(new MultiplyStrategy()); 33 34 result = context.getResult(9, 3); 35 36 System.out.println("mul: "+result); 37 } 38 }
输出结果:
上面只是用到策略模式,下面加上简单工厂模式
工厂类
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * Factory 6 */ 7 public class Factory { 8 public Strategy createStrategy(String str) 9 { 10 if("AddStrategy".equalsIgnoreCase(str)) 11 { 12 return new AddStrategy(); 13 } 14 else 15 if("SubStrategy".equalsIgnoreCase(str)) 16 { 17 return new SubStrategy(); 18 } 19 else 20 if("DivStrategy".equalsIgnoreCase(str)) 21 { 22 return new DivStrategy(); 23 } 24 else 25 if("MultiplyStrategy".equalsIgnoreCase(str)) 26 { 27 return new MultiplyStrategy(); 28 } 29 else 30 return null; 31 } 32 33 }
客户端类
1 package strategy; 2 /** 3 * 4 * @author CIACs 5 * Client 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 10 Context context = new Context(); 11 int result; 12 Strategy strategy; 13 Factory fac = new Factory(); 14 strategy = fac.createStrategy("AddStrategy"); 15 context.setStrategy(strategy); 16 result = context.getResult(9, 3); 17 System.out.println(result); 18 } 19 }
输出结果:
当然这里的工厂类中的if-else的使用是不太好的,简单工厂模式把生成策略类与客户端分离。
总结:
策略模式使开发人员能够开发出很多可替换的组件,而组件间是弱连接的,体现了代码的可重用行,弱连接也为以后开发新的组件打下了基础,具有较强的可扩展性,易于维护。策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给别的对象管理。客户端决定应该使用什么策略,因此客户端需要理解所有具体策略类之间的区别,这也增加了客户端的使用难度。