目录
- 概述
- 类图
- 案例
- 总结
- 附录
概述
策略模式(Strategy Pattern
)属于对象行为型模式,通过定义算法族,对每个算法的封装,最终使得不同算法可以相互替换,并且算法的变化不会影响使用算法的客户,此模式让算法的变化独立于使用算法的客户
❓为什么会存在策略模式?
软件开发中修改需求是常态,比如:今天让你设计一个求均值的算法,明天让你做一个求方差的算法,如果没有使用策略模式,每次设计完算法之后,都会造成算法调用方代码的修改,这并不符合开闭原则,所以策略模式就是想要做到:算法的变化并不会影响使用算法的客户(调用者)
✨策略模式中使用的设计原则:
- 将变化的代码从不变的代码中分离出来;
- 针对接口编程而不是具体类(定义策略接口);
- 多用组合/聚合少用继承(客户通过组合方式使用策略)
类图
将策略模式具体表示在 UML 中,它的类图如下:
策略模式主要存在三个角色:
角色 | 含义 |
---|
环境(Context) | 持有一个策略类的引用,最终给客户端调用 |
抽象策略(Strategy) | 公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现 |
具体策略(Concrete Strategy) | 实现了抽象策略定义的接口,提供具体算法的实现 |
案例
设计一个鸭子,它可以动态地改变叫声。这里的算法族是鸭子的叫声行为
1 2 3 4
| public interface QuackBehavior { void quack(); }
|
1 2 3 4 5 6 7
| public class Quack implements QuackBehavior { @Override public void quack() { System.out.println("quack!"); } }
|
1 2 3 4 5 6 7
| public class Squeak implements QuackBehavior{ @Override public void quack() { System.out.println("squeak!"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Duck { private QuackBehavior quackBehavior;
public void performQuack() { if (quackBehavior != null) { quackBehavior.quack(); } }
public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Test { public static void main(String[] args) { Duck duck = new Duck(); duck.setQuackBehavior(new Squeak()); duck.performQuack(); duck.setQuackBehavior(new Quack()); duck.performQuack(); } }
|
总结
🤔策略模式的确非常强大,但是我们能在什么场景使用策略模式?
- 使用策略模式可以避免使用多重条件语句,比如冗余的
if...else
语句或者switch...case
语句 - Spring 中的
InstantiationStrategy
使用了策略模式 - 线程池的拒绝策略,使用了策略模式
😣策略模式并不是万能的,与其他设计模式相同,使用设计模式会增加代码的复杂性,策略模式中,每添加一个策略就要增加一个类,当策略过多时会导致类数目庞大不易管理
附录
行为型 - 策略(Strategy)