一、策略模式
在策略(Strategy Pattern)中,一个类的行为或算法可以在运行时动态的更改。这种类型的设计模式属于行为模式(Behavioral Pattern-对象间通信)。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的context对象。策略对象改变context对象的执行算法。
二、介绍
意图: 定义一系列算法,把它们一个个封装起来,并且是她们可互相替换。
Define a family of algorithms, encapsulate each one, and make them interchangeable
主要解决: 在有多种算法相似的情况下,使用if...else 所带来的复杂和难以维护。
何时使用: 一个系统中有许多许多类,而区分它们的只是它们直接的行为。
如何解决: 将这些算法封装成一个一个类,任意替换。
关键代码: 实现同一个接口。
应用实例:
- 诸葛亮的锦囊妙计,每个锦囊就是一个策略。
- 旅行的出游方式,选择,️,,,,每一种旅行方式都是一个策略。
- Java AWT 中的LayoutManager。(这个不熟悉)
优点:
- 算法可以自由的切换。
- 避免使用多重条件判断。
- 扩展性良好。
缺点:
- 策略类会增多。
- 所有的策略类都需要对外暴露。
使用场景: - 如果在一个系统中有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有许多行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项: 如果一个系统中的策略多于4个,就是需要考虑使用混合模式,解决策略模式膨胀的问题。
三、实现
类结构图如下:
- Context角色:起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
- Strategy抽象策略角色:策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
- ConcreteStrategy具体策略角色:实现抽象策略中的操作,该类含有具体的算法。
- 创建策略接口(Strategy):
public interface Strategy { int doOperation(int operator1, int operator2); }
- 创建策略具体算法实现类(OperationAdd、OperationMultiply、OperationSubstract):
public class OperationAdd implements Strategy { @Override public int doOperation(int operator1, int operator2) { return operator1 + operator2; } }
创建Context类:
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public int executeStrategy(int operator1, int operator2) { return strategy.doOperation(operator1, operator2); } public void setStrategy(Strategy strategy) { this.strategy = strategy; } }
使用 Context 来查看当它改变策略 Strategy 时的行为变化。
public class Test { public static void main(String[] args) { int operator1 = 10; int operator2 = 2; int result = 0; Context ctx = new Context(new OperationAdd()); result = ctx.executeStrategy(operator1, operator2); System.out.println(operator1 + " + " + operator2 + " = " + result); ctx.setStrategy(new OperationMultiply()); result = ctx.executeStrategy(operator1, operator2); System.out.println(operator1 + " * " + operator2 + " = " + result); ctx.setStrategy(new OperationSubstract()); result = ctx.executeStrategy(operator1, operator2); System.out.println(operator1 + " - " + operator2 + " = " + result); } }
结果