1. 概述
本文将重点讲解状态模式(State Pattern)与策略模式(Strategy Pattern)的区别。这两个设计模式在结构上非常相似,因此很多开发者容易混淆。本文的核心目标是明确它们的设计意图、应用场景以及本质区别。
2. 策略模式(Strategy Pattern)
策略模式的核心目标是定义一组可互换的算法,形成一个算法族。 它允许客户端在运行时选择不同的实现逻辑。结构上主要包括两个部分:Context
(上下文)和多个实现相同接口的 Strategy
(策略):
举个例子:我们有一个用户列表,需要根据姓名排序用于客服系统,根据地理位置排序用于市场系统。如果逻辑直接写在客户端,会导致代码高度耦合、难以维护。
使用策略模式后,我们可以将排序逻辑抽象为策略接口,传入给排序类。这样不仅解耦了业务逻辑与算法实现,还支持运行时动态切换策略。
✅ 优点:
- 客户端无需关心具体实现细节
- 通过多态替代条件判断,提升可扩展性
- 易于新增或替换策略
❌ 缺点:
- 不同策略可能操作不同的数据结构,导致接口难以统一
- 某些策略的方法可能不会被使用,造成冗余
3. 状态模式(State Pattern)
状态模式可以看作是策略模式的延伸,它将对象的行为与状态绑定。 有两个核心前提:
- 对象的行为依赖其当前状态
- 状态之间可以互相转换
典型结构如下图所示:
一个经典的例子是自动取款机(ATM)。虽然接口一致,但插入卡前后、输入密码前后等不同状态下的行为完全不同。使用状态模式后,我们可以将每种状态的行为封装到各自的类中,使逻辑更清晰、更易维护。
状态模式的核心优势在于:
- 将状态逻辑外化,便于管理和修改
- 支持运行时行为切换(通过切换状态)
- 减少上下文中的条件判断,提升可读性
状态切换通常有两种方式:
- 由
Context
控制状态流转(适合流程简单的情况) - 由各个
State
自行决定下一步状态(适合复杂状态机)
⚠️ 后者虽然更灵活,但也可能增加状态之间的耦合度。
4. 状态模式 vs 策略模式
从 UML 结构上看,两者非常相似,但这只是表面现象。UML 图表无法体现设计意图和实际行为差异。
我们以汽车为例说明两者的区别:
- 状态模式适用场景:发动机是否启动、电池是否有电、油箱是否空等状态都会影响汽车的行为。这些状态是对象生命周期的一部分,行为会随着状态变化而变化。
- 策略模式适用场景:汽车使用汽油发动机还是柴油发动机,这个“发动机类型”是一个策略,可以在不改变对象状态的前提下更换。它更像是一个配置项,而不是状态。
总结如下:
✅ 状态模式:
- 行为由当前状态决定
- 状态之间有自然流转关系
- 通常由 Context 或 State 自身控制状态变化
✅ 策略模式:
- 提供不同算法实现
- 策略之间无依赖、无流转
- 通常由外部设置,运行期间可能不变化
5. 总结
状态模式和策略模式在结构上相似,但它们的设计目标和适用场景截然不同:
- 策略模式 用于封装算法,支持运行时动态切换
- 状态模式 用于封装状态行为,状态之间有流转关系
理解它们的区别,有助于我们在实际开发中选择合适的设计模式,避免滥用或误用。