策略模式(Strategy Pattern):算法的封装与灵活切换
策略模式是行为型设计模式的一种,核心思想是定义一系列算法,将每个算法封装成独立的策略类,使它们可以相互替换,从而让算法的变化独立于使用算法的客户端。这种模式就像 “出行方式的选择”—— 无论是步行、骑车还是开车,目的都是到达目的地,只是方式不同,客户端可根据需求灵活切换。
策略模式的核心结构
策略模式通过三个核心角色实现算法的封装与切换,结构清晰且职责分明:
策略接口(Strategy)
- 定义所有算法的公共接口,声明算法的核心方法(如计算、执行等)。
- 示例:
PaymentStrategy(支付策略接口,定义pay(double amount)方法)。
具体策略(ConcreteStrategy)
- 实现策略接口,封装具体的算法逻辑,是策略模式的 “可替换单元”。
- 示例:
AlipayStrategy(支付宝支付)、WechatPayStrategy(微信支付)。
上下文(Context)
- 使用策略的客户端角色,持有策略接口的引用,负责将具体策略传递给客户端,或根据场景选择策略。
- 上下文不直接实现算法,而是委托给具体策略执行,自身仅关注 “何时使用算法” 而非 “如何实现算法”。
- 示例:
Order(订单上下文,通过支付策略完成支付)。
代码实现示例
以 “订单支付系统” 为例,展示策略模式的应用:订单可通过支付宝、微信等不同方式支付,客户端可动态选择支付方式。
1. 策略接口(Strategy)
1 | // 策略接口:支付策略 |
2. 具体策略(ConcreteStrategy)
1 | // 具体策略1:支付宝支付 |
3. 上下文(Context)
1 | // 上下文:订单 |
4. 客户端使用
1 | public class StrategyDemo { |
策略模式的核心优势
- 算法的灵活切换
客户端可在运行时动态更换策略(如订单支付时从支付宝切换到微信),无需修改上下文或其他策略的代码,符合开闭原则。 - 算法的封装与隔离
每个算法被封装在独立的策略类中,避免了算法逻辑与客户端代码的混杂(如消除大量if-else判断),提高代码可读性和可维护性。 - 易于扩展新算法
新增算法时,只需实现策略接口并添加具体策略类,无需修改现有代码(如新增 “银行卡支付” 只需添加BankCardStrategy)。 - 单一职责原则
每个策略类仅负责实现一种算法,上下文仅负责协调策略的使用,职责清晰,降低耦合度。
适用场景
- 存在多种可替换的算法
当系统中某个功能有多种实现方式(如排序算法、支付方式、日志记录方式),且需要根据场景动态选择时。 - 避免冗长的条件判断
若代码中存在大量if-else或switch语句用于选择不同算法(如if (type == "ALIPAY") { ... } else if (type == "WECHAT") { ... }),策略模式可将这些判断逻辑转移为策略的动态切换。 - 算法需要独立扩展
算法的变化不应影响客户端或其他算法(如新增支付方式不应修改订单类)。 - 客户端需要知道所有策略
客户端需了解不同策略的差异,以便选择合适的策略(如用户需手动选择支付方式)。
优缺点分析
优点
- 灵活性高:策略可动态切换,适应不同场景需求。
- 可维护性强:算法封装在独立类中,便于修改和测试。
- 可扩展性好:新增策略无需修改现有代码,符合开闭原则。
缺点
- 客户端需了解策略:客户端必须知道所有策略的存在及差异,才能选择合适的策略(增加了客户端的使用成本)。
- 策略类数量膨胀:若算法过多,会导致策略类数量激增(可通过结合工厂模式缓解)。
经典应用案例
- Java 集合框架的排序
Collections.sort()方法接收Comparator接口(策略接口),客户端可通过实现Comparator定义不同的排序策略(如按名称排序、按年龄排序)。 - Spring 的资源访问
Spring 的Resource接口(策略接口)定义了资源访问的方法,具体策略如FileSystemResource(文件系统资源)、ClassPathResource(类路径资源),可根据资源位置动态选择。 - 日志框架的输出策略
日志框架(如 Logback)中,日志可输出到控制台、文件或数据库,每种输出方式对应一个策略类,可通过配置动态切换。 - 电商系统的促销策略
订单结算时可应用不同的促销策略(满减、折扣、优惠券),每种策略对应一个具体策略类,上下文根据订单金额或用户等级选择策略。
总结
策略模式通过 “定义策略接口、封装具体算法、上下文协调使用” 的方式,实现了算法的灵活切换与扩展。其核心价值在于分离算法的定义与使用,消除条件判断语句,使系统更易于维护和扩展。在实际开发中,策略模式常与工厂模式结合使用(由工厂负责创建策略),以降低客户端对策略的直接依赖
