1. 什么是策略模式?
策略模式(Strategy Pattern) 是一种行为型设计模式,通过定义一组可互换的算法族,并将每个算法封装成独立类,使得算法可以独立于客户端变化。其核心是
将算法与使用场景解耦,避免复杂的条件分支,提升系统扩展性。
📜 设计原则体现
符合 开闭原则(新增策略无需修改已有代码)、单一职责原则(每个策略类只负责一个算法)
2. 核心思想
核心点 |
说明 |
算法抽象化 |
通过接口定义算法规范,隐藏具体实现细节 |
动态替换 |
运行时通过注入不同策略对象切换算法(如:设置不同的折扣策略) |
消除条件分支 |
用多态代替 if-else /switch-case ,使代码更简洁 |
3. 代码案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
public interface DiscountStrategy { void applyDiscount(double price); }
public class NineDiscount implements DiscountStrategy { @Override public void applyDiscount(double price) { System.out.printf("[9折] 折后价: %.2f\n", price * 0.9); } }
public class EightDiscount implements DiscountStrategy { @Override public void applyDiscount(double price) { System.out.printf("[8折] 折后价: %.2f\n", price * 0.8); } }
public class PriceCalculator { private DiscountStrategy strategy;
public PriceCalculator(DiscountStrategy strategy) { this.strategy = strategy; }
public void setStrategy(DiscountStrategy strategy) { this.strategy = strategy; }
public void calculate(double price) { strategy.applyDiscount(price); } }
public class Client { public static void main(String[] args) { PriceCalculator calculator = new PriceCalculator(new NineDiscount()); calculator.calculate(100);
calculator.setStrategy(new EightDiscount()); calculator.calculate(100); } }
|
4. 类结构图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| +---------------------+ | DiscountStrategy |<-----------------------------+ +---------------------+ | | + applyDiscount() | | +---------------------+ | ▲ | | | +---------------------+ +---------------------+ | | NineDiscount | | EightDiscount | | +---------------------+ +---------------------+ | | + applyDiscount() | | + applyDiscount() | | +---------------------+ +---------------------+ | ▲ | | | +---------------------+ | | PriceCalculator |-------------------------------+ +---------------------+ | - strategy | | + setStrategy() | | + calculate() | +---------------------+
|
5. 模式优势
优势 |
说明 |
高扩展性 |
新增策略只需实现接口,无需修改上下文类 |
算法复用 |
同一策略可被多个上下文复用(如不同模块使用相同折扣逻辑) |
提升可维护性 |
算法变化被隔离在策略类中,降低对整体系统的影响 |
简化单元测试 |
每个策略可独立测试,无需耦合客户端逻辑 |
6. 注意事项
6.1 潜在问题
问题 |
解决方案 |
策略类数量膨胀 |
对简单策略使用 Lambda 或匿名类 |
客户端感知策略差异 |
结合工厂模式隐藏策略创建细节 |
策略无状态 |
将策略类设计为无状态对象,通过享元模式复用 |
6.2 最佳实践
- 优先组合而非继承:通过将策略接口组合到上下文中,而非使用继承层次。
- 与工厂模式结合:用
StrategyFactory
管理策略对象的创建逻辑。
- 策略命名规范化:使用
XxxStrategy
后缀提高代码可读性(如 PaymentStrategy
)。
7. 实际应用场景
- 支付系统:切换不同的支付方式(支付宝、微信、信用卡)。
- 游戏 AI:根据敌人类型切换攻击策略。
- 数据解析:支持 JSON、XML、CSV 等多种格式解析。
- Spring 框架:
ResourceLoader
的资源加载策略、PlatformTransactionManager
的事务管理策略。
8. 附录
8.1 参考资料
8.2 延伸阅读