策略模式(Strategy Pattern)是一种行为型设计模式,通过定义算法族并封装每个算法,使其可相互替换,从而让算法独立于使用它的客户端而变化。以下是该模式的系统性解析:
一、核心定义与设计目标
-
定义
策略模式将算法或行为抽象为独立接口,具体策略类实现该接口,客户端通过上下文(Context)动态选择策略,实现运行时灵活切换。例如,电商平台根据促销类型(满减、折扣、积分)动态选择计价策略。 -
设计目标
- 解耦算法与业务逻辑:避免硬编码条件分支(如
if-else
)。 - 扩展性:新增策略无需修改现有代码,符合开闭原则。
- 复用性:相同策略可被多个上下文复用。
- 解耦算法与业务逻辑:避免硬编码条件分支(如
二、模式结构与角色划分
-
核心角色
- 抽象策略(Strategy):定义算法接口(如
DiscountStrategy
)。 - 具体策略(ConcreteStrategy):实现接口的具体算法(如
HolidayDiscount
、MemberDiscount
)。 - 上下文(Context):持有策略对象,通过方法调用策略(如
Order
类使用策略计算价格)。
- 抽象策略(Strategy):定义算法接口(如
-
UML类图示例
+--------------------+ +---------------------+
| Strategy |<|------|>| Context |
| +executeAlgorithm()| | -strategy: Strategy |
+--------------------+ +---------------------+
▲ ▲
| |
+-------------------+ +-------------------+
| ConcreteStrategyA | | Client |
+-------------------+ +-------------------+
- 实现方式
- 经典策略模式:通过接口与实现类显式定义策略。
- 动态策略注入:结合工厂模式或依赖注入框架(如Spring)管理策略。
三、优缺点分析
优点
- 消除条件分支:替代复杂的
if-else
或switch-case
逻辑。 - 灵活扩展:新增策略只需添加新类,无需修改上下文)。
- 单一职责:每个策略类仅关注自身算法。
缺点
- 类数量膨胀:每个算法对应一个类,可能增加系统复杂度。
- 客户端需感知策略:客户端需了解不同策略的差异以正确选择。
四、适用场景
- 多算法动态切换
- 支付方式选择(支付宝、微信、银联)。
- 数据排序策略(快速排序、归并排序)。
- 业务规则复杂多变
- 促销活动计算(满减、折扣、秒杀)。
- 日志处理策略(本地存储、云存储、邮件通知)。
- 隐藏算法实现细节
- 加密算法(AES、RSA)的动态选择。
五、实现示例(Java)
以电商促销策略为例:
// 抽象策略接口
public interface PromotionStrategy {
double applyPromotion(double price);
}
// 具体策略:满减
public class FullReductionStrategy implements PromotionStrategy {
@Override
public double applyPromotion(double price) {
return price >= 200 ? price - 50 : price;
}
}
// 具体策略:折扣
public class DiscountStrategy implements PromotionStrategy {
@Override
public double applyPromotion(double price) {
return price * 0.8;
}
}
// 上下文类
public class Order {
private PromotionStrategy strategy;
public void setStrategy(PromotionStrategy strategy) {
this.strategy = strategy;
}
public double calculateFinalPrice(double price) {
return strategy.applyPromotion(price);
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Order order = new Order();
order.setStrategy(new FullReductionStrategy());
System.out.println(order.calculateFinalPrice(300)); // 输出:250.0
}
}
六、实际应用案例
- Java IO流
BufferedInputStream
封装缓冲策略,提升读取性能。
- Spring框架
- 事务管理策略(JDBC、JTA)通过
PlatformTransactionManager
接口动态切换。
- 事务管理策略(JDBC、JTA)通过
- 日志框架
- Logback 根据策略选择日志输出方式(控制台、文件、数据库)。
七、与其他模式的对比
模式 | 核心差异 |
---|---|
工厂模式 | 关注对象创建,策略模式关注算法选择 |
命令模式 | 封装请求为对象,策略模式封装算法 |
状态模式 | 状态驱动行为变化,策略模式由客户端主动切换 |
八、总结
策略模式通过算法抽象与动态替换,有效解决复杂条件分支与算法扩展性问题。其核心价值在于提升代码的灵活性和可维护性,尤其适用于算法频繁变更或需多版本并存的场景。开发中需注意合理划分策略边界,避免过度设计导致类膨胀。结合工厂模式或依赖注入框架(如Spring),可进一步提升策略管理的优雅性。