一.应用背景
在软件开发中常常遇到这种情况,实现某一个功能有多种算法或者策略,我们可以根据应用场景的不同选择不同的算法或者策略来完成该功能。把一个类(A)中经常改变或者将来可能改变的部分提取出来,作为一个接口(B),然后在类(A)中包含这个接口(B),这样类(A)的实例在运行时就可以随意调用实现了这个接口的类(C)的行为。比如定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换,使得算法可独立于使用它的客户而变化。这就是策略模式。
(1)如果一个系统要动态地在几种算法之间选择其中一种 => 那就快用策略模式吧骚年!
(2)如果有难以维护的多重if-else条件选择语句是为了实现对象的行为 => 那就快用策略模式吧骚年!
(3)不希望客户知道复杂的与算法有关的数据结构,可以将其封装到策略中 => 提高算法的保密性和安全性!
二.优、缺点
优点:
(1)提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择具体算法或行为,也可以灵活地增加新的算法或行为。
(2)避免了多重的if-else条件选择语句,利于系统的维护。
(3)提供了一种算法的复用机制,不同的环境类可以方便地复用这些策略类。
缺点:
(1)客户端需要知道所有的策略类,并自行决定使用哪一个策略 => 只适用于客户端了解所有策略算法的情况。
(2)将造成系统产生很多的具体策略类,任何细小的变化都将导致系统要增加一个具体策略类 => 类的个数也许会超出预期。
(3)无法在客户端同时使用多个策略类 => 客户端每次只能使用一个策略类。
三.组成
第一步:定义抽象策略角色
为策略对象定义一个公共的接口
/** * 第一步:定义抽象策略角色 * 为策略对象定义一个公共的接口 */ public interface Strategy { int calc(int num1, int num2); }
第二步:定义具体策略角色(实际上就是实现上面定义的公共接口)
* 加法策略
/** * 第二步:定义具体策略角色(实际上就是实现上面定义的公共接口) * 加法策略 */ public class AddStrategy implements Strategy { @Override public int calc(int num1, int num2) { return num1 + num2; } }
* 减法策略
/** * 定义具体策略角色(实际上就是实现上面定义的公共接口) * 减法策略 */ public class SubtractStrategy implements Strategy { @Override public int calc(int num1, int num2) { return num1 - num2; } }
第三步:定义环境角色,内部持有一个策略类的引用
/** * 环境角色 * 第三步:定义环境角色,内部持有一个策略类的引用 */ public class Environment { /** * 持有对策略类的引用 */ private Strategy strategy; public Environment(Strategy strategy) { this.strategy = strategy; } public int calulate(int a, int b) { return strategy.calc(a, b); } }
测试 * 测试类
*/ public class StrategyTest { public static void main(String[] args) { /** * 传入具体的策略类 */ Environment environment = new Environment(new AddStrategy()); int calulate = environment.calulate(20, 30); System.out.println("加法策略结果:"+calulate); Environment environment1 = new Environment(new SubtractStrategy()); int calulate1 = environment1.calulate(20, 30); System.out.println("减法策略结果:"+calulate1); } }
运行结果:
加法策略结果:50
减法策略结果:-10