设计模式之策略模式
诞生的目的
在传统的软件开发中,当需要为一个问题提供多种算法时,开发者往往采用以下两种方式:
- 在一个类中提供多个方法,每个方法对应一种算法实现
- 在一个方法中通过 if…else 或 switch 条件语句进行分支选择
这两种方式都属于硬编码,带来的问题非常明显:
- 维护困难:增加新算法或修改现有算法,都需要修改原有类的源代码
- 代码臃肿:大量算法堆积在同一个类中,代码变得复杂且难以阅读
- 违反开闭原则:对扩展不开放,对修改不封闭——每次增加新算法都要修改已有代码
- 团队协作冲突:多人同时修改同一个庞大的类,容易产生代码冲突
策略模式正是为了解决这些问题而诞生————将算法从使用它的客户类中抽离出来,独立封装,使算法可以独立变化。
核心思想
找出应用中可能变化的部分,把它们独立出来,不要和那些不需要变化的代码混在一起。同时,针对接口编程,而不是针对实现编程。
结构
策略模式涉及三个核心角色:
| 角色 | 说明 |
|---|---|
| 抽象策略(Strategy) | 定义公共接口,所有具体策略都必须实现此接口 |
| 具体策略(Concrete Strategy) | 实现抽象策略接口,提供具体的算法实现 |
| 环境类(Context) | 持有抽象策略对象的引用,负责调用策略,客户端通过环境类使用策略 |
UML类图结构如下:
1 | ┌─────────────┐ ┌──────────────────┐ |
结构代码范式
Strategy : 定义所有算法的公共接口(AlgorithmInterface)。Context 使用这个接口去调用 ConcreteStrategy 定义的具体算法。
1 | abstract class Strategy { |
ConcreteStrategy : 实现 Strategy 中的算法接口(AlgorithmInterface)。
1 | class ConcreteStrategyA extends Strategy { |
Context : 用一个 ConcreteStrategy 来配置。维护一个对 Strategy 对象的引用。
1 | class Context { |
客户端
1 | public class StrategyPattern { |
输出
1 | 算法A |
比如可以在Strategy的实现类上面都加上@Component注解,在context中依赖注入的三行代码变成下面这样,就可以自动获取Strategy的实现类为val的map。
1
2
3
4
5
private final Map<String, Strategy> StrategyMap;
public Context(Map<String, Strategy> StrategyMap) {
this.StrategyMap = StrategyMap;
}这是因为spring可以自动注入同类型 Bean 的集合。它不是某个特殊的配置,而是 Spring 容器的内置行为。可以使用这个来注入map,在策略模式中经常使用。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 coder-xuyong!
评论







