参考资料:
漫话:如何给女朋友解释什么是策略模式?
一、 定义
Strategy模式也叫策略模式是行为模式之一,它对一系列的算法加以封装,这里的算法即一系列策略的集合。为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略)。Strategy模式主要用来平滑地处理算法的切换 。
二、一般结构
- 抽象策略 :一个Strategy接口,定义操作接口
- 具体策略:若干实现Strategy接口的操作的类
-
上下文:
- 该上下文定义Strategy,构造方法根据传入的 实现Strategy接口的操作的类 定位不同的策略
- 该上下文会执行策略
使用策略模式可以避免条件选择(大量的if..else
),使用策略的切换代替if...else
,实际上是通过策略上下文实现继承替换,达到策略的切换。
优点
- 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
- 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
- 使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。这种策略类的创建及选择其实也可以通过工厂模式来辅助进行。
- 由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。可以通过使用享元模式在一定程度上减少对象的数量
demo
-
抽象策略。定义操作接口
package com.icarus.icarusboot.gof.strategy; /** * 抽象策略,定义操作接口 * * @ClassName: Strategy * @author: yihong * @since: 2019/10/28 14:58 */ public interface Strategy { public int doOperation(int num1, int num2); }
-
具体策略
减法package com.icarus.icarusboot.gof.strategy; /** * 减法 * * @ClassName: OperationSubstrat * @author: yihong * @since: 2019/10/28 15:00 */ public class OperationSubstract implements Strategy{ @Override public int doOperation(int num1, int num2) { return num1 - num2; } }
加法
package com.icarus.icarusboot.gof.strategy; /** * 加法 * * @ClassName: OperationAdd * @author: yihong * @since: 2019/10/28 14:59 */ public class OperationAdd implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 + num2; } }
乘法
package com.icarus.icarusboot.gof.strategy; /** * 乘法 * * @ClassName: OperationMultiply * @author: yihong * @since: 2019/10/28 15:07 */ public class OperationMultiply implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 * num2; } }
-
上下文
package com.icarus.icarusboot.gof.strategy; /** * 上下文 * * @ClassName: OperationContext * @author: yihong * @since: 2019/10/28 15:08 */ public class OperationContext { private Strategy strategy; public OperationContext(Strategy strategy){ this.strategy = strategy; } public int executeStrategy(int num1, int num2){ return this.strategy.doOperation(num1,num2); } }
-
执行策略
package com.icarus.icarusboot.gof.strategy; /** * TODO * * @ClassName: StrategyPatternDemo * @author: yihong * @since: 2019/10/28 15:10 */ public class StrategyPatternDemo { public static void main(String[] args) { boolean isSon = Strategy.class.isAssignableFrom(OperationAdd.class); String result = isSon ? "是" : "不是"; System.out.println("OperationAdd " + result + " Strategy 的基类" ); OperationContext operationContext = new OperationContext(new OperationAdd()); System.out.println("10 + 5 = " + operationContext.executeStrategy(10, 5)); operationContext = new OperationContext(new OperationSubstract()); System.out.println("10 - 5 = " + operationContext.executeStrategy(10, 5)); operationContext = new OperationContext(new OperationMultiply()); System.out.println("10 * 5 = " + operationContext.executeStrategy(10, 5)); } }
看这个demo
还是很简单的,策略模式也好理解,但是运用到实际开发中就比较难了~如何让自己的代码变得更漂亮,这是一个问题。