策略模式定义了一系列算法(算法族),各可以相互替换,客户端可根据实际情况选择使用哪一种算法,算法的变化不会影响使用算法的客户。
策略模式核心结构:
1.抽象策略接口或抽象类 Strategy:具体的策略的规范。
2.具体策略类 Concrete Strategy :抽象策略的实现类。
3. 上下文策略类 Context:持有一个策略类的引用,最终给客户端调用。
UML类图如下:
下面我们以实例来理解策略模式的运用:
中国移动对不同客户群有不同的流量套餐,同样是50元套餐,普通用户可获得流量50G,全球通用户可获得100G,企业用户可获得200G,对,中国移动就是这么黑。营业厅办理业务时,根据用户不同类型,提供不同的流量策略。
package net.mosang.strategy; /** * 抽象策略类 * @author Heiry * */ public interface Strategy { public int getStrategy(int standardDataFlow); //标准手机流量 }
package net.mosang.strategy; /** * 普通用户策略:50G/月 * @author Heiry * */ public class standard implements Strategy { @Override public int getStrategy(int standardDataFlow) { System.out.println("普通用户,每月"+standardDataFlow+"流量。"); return standardDataFlow; } }
package net.mosang.strategy; /** * 全球通用户策略:100G/月 * @author Heiry * */ public class GSM implements Strategy { @Override public int getStrategy(int standardDataFlow) { System.out.println("全球通用户,每月"+standardDataFlow*2+"G流量。"); return standardDataFlow*2; } }
package net.mosang.strategy; /** * 企业用户策略:200G/月 * @author Heiry * */ public class Enterprise implements Strategy { @Override public int getStrategy(int standardDataFlow) { System.out.println("企业用户,每月"+standardDataFlow*4+"G流量。"); return standardDataFlow*4; } }
package net.mosang.strategy; /** * 上下文类,用于策略切换和客户端调用; * 通过上下文类,算法与客户端类分离 * @author Heiry * */ public class Context { private Strategy strategy ; //持有对具体策略的引用 public void getStrategy(int i) { strategy.getStrategy(i); //调用具体策略 } public Context(Strategy strategy) { this.strategy = strategy; } public Strategy getStrategy() { return strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } }
package net.mosang.strategy; /** * 客户端类 * @author Heiry * */ public class Client { public static void main(String[] args) { int standardFlow = 50 ; //普通基础流量50G Strategy s1 = new GSM(); Strategy s2 = new Enterprise(); Strategy s3 = new standard(); Context c1 = new Context(s1); c1.getStrategy(standardFlow); System.out.println("#####################################"); Context c2 = new Context(s2); c2.getStrategy(standardFlow); System.out.println("#####################################"); Context c3 = new Context(s3); c3.getStrategy(standardFlow); } }
输出结果:
全球通用户,每月100G流量。 ##################################### 企业用户,每月200G流量。 ##################################### 普通用户,每月50流量。
通过以上实例,我们看到,策略模式避免了复杂策略而不可避免的庞大而难以维护的if…else判断,可以在不修改原代码的情况下,灵活增加新算法,符合开闭原则。
>>