一个非常简单的模式,先看类图:
涉及到三个角色
* context封装角色:这个模式的核心。也叫上下文角色屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
1 //封装角色 2 public class Context{ 3 private Strategy strategy = null; 4 //注入抽象策略 5 public Context(Strategy strategy){ 6 this.strategy = strategy; 7 } 8 //执行策略 9 public void doanything(){ 10 this.strategy.dosomething(); 11 } 12 }
* strategy抽象策略角色:策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
1 //抽象策略角色 2 public interface Strategy{ 3 //运算法则 4 public void dosomething(); 5 }
* concretestrategy具体策略角色:实现抽象策略中的操作,该类含有具体的算法
1 //具体策略A 2 public class ContextStrategyA implements Strategy{ 3 @Override 4 public void dosomething() { 5 System.out.println("执行方案A"); 6 } 7 }
//具体策略B public class ContextStrategyB implements Strategy{ @Override public void dosomething() { System.out.println("执行方案B"); } }
客户端代码:
1 //客户端代码 2 public class Client { 3 public static void main(String[] args) { 4 Strategy strategy = null; 5 Context context = null; 6 //使用方案A 7 strategy = new ContextStrategyA(); 8 context = new Context(strategy); 9 context.doanything(); 10 //使用方案B 11 strategy = new ContextStrategyB(); 12 context = new Context(strategy); 13 context.doanything(); 14 } 15 }
总结:策略模式的本质就是分离算法,选择实现。
优点:算法可自由切换,体现了开闭原则和里氏替换原则
缺点:使用者必须知道所有的具体策略,这就产生了依赖,违反了迪米特法则。但是可通过和其他模式组合使用来消除这个问题,如使用工厂模式等等。
与状态模式模式的区别:
两个模式从结构上看是一样的但是侧重点不同。状态模式根据状态变化来选择相应的行为,在实现功能的同时会伴随着状态的更改,这个状态是具有动态性的。
策略模式则是根据调用者的需要来选择具体的策略,策略之间是平等可替换的,不需要关心使用者的状态。
应用场景:算法需要自由切换的场景。如产品打折,钻石会员卡5折,普通会员卡8折,只需要两个算法实现策略接口就可以自由切换打折方案。