策略模式是什么
策略模式把可互换的算法封装成独立实现,由调用方在运行期选择:调用方不再写按类型分支的判断,新增变体只需加一个实现类,各算法也能单独测试。上下文只持有接口,不感知具体算法,因此实现可以自由替换。
基本信息
| 意图 | 算法族可替换,运行期选择 |
|---|---|
| 收益 | 消除条件分支,算法独立演进 |
| 典型实例 | 定价策略、压缩算法、路由规则 |
| 结构 | 上下文持有策略接口,多个实现类 |
| 关联模式 | 工厂或注册表负责选择实现 |
典型使用场景
- 同一计算在不同客户或地区有不同规则
- 压缩、加密、序列化算法的切换
- 路由与限流策略按环境调整
- 校验规则集合可配置
- 重试与退避策略按下游服务区分
Java 示例
Java 示例
interface Compressor { byte[] compress(byte[] in); }
class GzipCompressor implements Compressor { ... }
class ZstdCompressor implements Compressor { ... }
class Archiver {
private final Compressor compressor;
Archiver(Compressor compressor) { this.compressor = compressor; }
byte[] save(byte[] data) { return compressor.compress(data); }
}上下文数据怎么给
| 方案 | 适用 | 代价 |
|---|---|---|
| 整体传上下文 | 策略需要多项数据 | 接口与领域对象耦合 |
| 只传必要参数 | 策略只依赖少量输入 | 参数增多时需要重构接口 |
| 策略持有配置 | 参数固定而实现不同 | 需注意策略对象是否有状态 |
策略对象尽量无状态:如果实现里保存中间结果,被复用或并发调用时容易出现难复现的问题;配置类参数应在构造时固定。
选择逻辑放哪里
- 按类型固定选择:用映射注册表在组装层集中装配
- 按配置动态选择:读取配置后交给工厂创建
- 按请求内容选择:在选择器里判断,策略本身保持无状态
- 按运行环境选择:启动时决定一次,运行期不再变化
为了让策略拿到全部数据而把整个上下文塞进接口,会让接口与领域对象强耦合:日后领域结构一改,所有策略都要跟着改。
如果选择逻辑本身很复杂,它可能就是一个独立职责:抽成选择器或注册表集中管理,比散落在业务代码里逐处判断更容易测试与替换。