如下是本文目录1. 为什么需要策略模式1.1 使用策略模式要解决的核心痛点1.2 正确典型使用场景1.3 不适合策略模式的场景2. 五种常见实现方式2.1 基础接口实现式原生标准2.2 枚举策略式极简无类爆炸2.3 工厂策略整合式解耦增强2.4 Lambda匿名策略式轻量化极简2.5 Spring容器策略式工程实战主流2.6 五种实现方式对比表2.7 高级拓展组合策略多策略叠加执行2.8 拓展案例文件加密策略2.9 策略模式UML结构图2.10 JDK标准库原生策略模式落地面试高频2.11 相似设计模式核心区分表3. 策略模式核心痛点与解决办法3.1 策略类过多类爆炸3.2 策略分发硬编码3.3 空策略、未知策略容错3.4 策略重复创建、性能冗余4. 总结1. 为什么需要策略模式策略模式是行为型设计模式核心目标定义一系列独立的算法业务策略将每个算法封装为独立类让算法可以互相替换且算法的变化不会影响调用算法的客户端完美实现业务算法与业务调用逻辑的解耦。换句话讲策略模式就是把多变的业务算法单独封装成一个个可替换的独立类外部调用代码只负责调度不需要关心算法内部细节换算法不用改主流程实现算法和业务代码解绑。1.1 使用策略模式要解决的核心痛点a. 业务中大量分支判断if-else/switch随着策略增多代码臃肿冗长、维护成本极高b. 算法逻辑高度耦合在业务主类中修改、新增算法需要改动核心业务代码违反开闭原则c. 不同业务算法逻辑混杂代码可读性差容易出现分支逻辑冲突、修改牵一发而动全身的问题d. 算法无法独立复用、单独测试多场景复用相同算法需要重复编码。1.2 正确典型使用场景a.多条件分支业务计算订单支付方式微信/支付宝/银行卡、折扣计算满减/折扣/优惠券、运费计算b.多类型数据处理策略文件解析Excel/Word/PDF、消息推送短信/邮件/APP推送、日志输出控制台/文件/数据库c.业务规则动态切换会员等级权益计算、风控校验规则、排序筛选策略、汇率换算策略d.框架层级算法替换线程池拒绝策略、Spring资源加载策略、序列化策略、缓存淘汰策略。1.3 不适合策略模式的场景a.策略极少变动、分支固定仅1-2个固定分支业务终身不会新增策略使用if-else更简洁b.算法逻辑极其简单单句代码即可实现的分支逻辑拆分策略类会造成类爆炸、过度设计c.策略之间存在强依赖、无法独立拆分多个算法逻辑耦合绑定拆分后会增加代码复杂度d.临时一次性业务策略无需复用、无需扩展的临时分支逻辑无需封装策略。2. 五种常见实现方式策略模式三大标准核心角色a.Strategy策略接口定义所有算法统一公共规范对外暴露统一执行方法b.ConcreteStrategy具体策略实现类独立实现接口封装单一算法逻辑单一职责c.Context上下文调度类持有策略对象引用提供动态修改策略入口接收客户端请求并委托策略执行。2.1 基础接口实现式原生标准特点定义统一策略接口不同策略实现接口上下文类持有策略对象对外提供统一调用入口是最经典、最标准的策略模式实现。// 1. 统一策略接口定义算法规范 public interface DiscountStrategy { // 计算折扣后价格 BigDecimal calculatePrice(BigDecimal originalPrice); } // 2. 具体策略实现1无优惠 public class NoDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice; } } // 3. 具体策略实现2八折优惠 public class EightDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.multiply(new BigDecimal(0.8)); } } // 4. 具体策略实现3满减优惠 public class FullReductionStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { // 满100减20 return originalPrice.compareTo(new BigDecimal(100)) 0 ? originalPrice.subtract(new BigDecimal(20)) : originalPrice; } } // 5. 上下文类统一调度入口持有策略 public class DiscountContext { // 持有策略接口引用运行时通过传入不同实现类来切换优惠算法 这也是JAVA中多态的核心运用 private DiscountStrategy discountStrategy; // 注入策略 public DiscountContext(DiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } // 动态修改策略 public void setDiscountStrategy(DiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } // 对外统一调用方法 public BigDecimal executeCalculate(BigDecimal originalPrice) { return discountStrategy.calculatePrice(originalPrice); } } // 测试使用 public class StrategyTest { public static void main(String[] args) { DiscountContext context new DiscountContext(new EightDiscountStrategy()); System.out.println(八折后价格 context.executeCalculate(new BigDecimal(200))); // 动态切换策略 context.setDiscountStrategy(new FullReductionStrategy()); System.out.println(满减后价格 context.executeCalculate(new BigDecimal(200))); } }适用场景策略数量适中、需要动态切换策略、常规业务解耦场景是企业开发通用首选。优缺点结构清晰、完全符合开闭原则、策略可独立扩展缺点是策略较多时会产生大量独立策略类。2.2 枚举策略式极简无类爆炸特点将所有策略封装在枚举内部通过枚举常量区分不同策略整合策略定义、实现、分发无需创建大量独立实现类代码极简。// 枚举策略整合所有折扣算法 public enum DiscountEnumStrategy { // 枚举常量对应不同策略 NO_DISCOUNT(1, 无优惠) { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice; } }, EIGHT_DISCOUNT(2, 八折优惠) { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.multiply(new BigDecimal(0.8)); } }, FULL_REDUCTION(3, 满减优惠) { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.compareTo(new BigDecimal(100)) 0 ? originalPrice.subtract(new BigDecimal(20)) : originalPrice; } }; // 策略编码、描述 private final int code; private final String desc; DiscountEnumStrategy(int code, String desc) { this.code code; this.desc desc; } // 抽象策略方法由每个枚举常量实现 public abstract BigDecimal calculatePrice(BigDecimal originalPrice); // 根据code获取对应策略 public static DiscountEnumStrategy getStrategyByCode(int code) { for (DiscountEnumStrategy strategy : values()) { if (strategy.code code) { return strategy; } } throw new IllegalArgumentException(无效的优惠策略编码); } // getter方法 public int getCode() { return code; } public String getDesc() { return desc; } } // 测试使用 public class EnumStrategyTest { public static void main(String[] args) { // 根据编码获取策略并执行 DiscountEnumStrategy strategy DiscountEnumStrategy.getStrategyByCode(2); System.out.println(strategy.getDesc() 价格 strategy.calculatePrice(new BigDecimal(200))); } }适用场景策略固定、不会频繁新增策略数量可控的业务场景替代大量简单策略类。优缺点杜绝类爆炸、代码集中统一管理、调用简洁缺点是策略逻辑复杂时枚举类会过于臃肿不适合复杂算法。2.3 工厂策略整合式解耦增强特点结合简单工厂模式新增策略工厂类统一创建、分发策略对象彻底屏蔽策略创建细节客户端无需感知具体策略实现类进一步解耦。// 1. 策略接口同基础实现 public interface DiscountStrategy { BigDecimal calculatePrice(BigDecimal originalPrice); } // 2. 具体策略实现 public class NoDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice; } } public class EightDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.multiply(new BigDecimal(0.8)); } } // 3. 策略工厂类统一生产策略 public class StrategyFactory { // 缓存所有策略避免重复创建 private static final MapString, DiscountStrategy STRATEGY_CACHE new HashMap(); // 静态初始化所有策略 static { STRATEGY_CACHE.put(noDiscount, new NoDiscountStrategy()); STRATEGY_CACHE.put(eightDiscount, new EightDiscountStrategy()); } // 根据key获取策略 public static DiscountStrategy getStrategy(String strategyKey) { DiscountStrategy strategy STRATEGY_CACHE.get(strategyKey); if (strategy null) { throw new IllegalArgumentException(不存在该优惠策略); } return strategy; } } // 4. 上下文调用 public class FactoryStrategyContext { public BigDecimal executePrice(String strategyKey, BigDecimal originalPrice) { // 工厂获取策略直接执行 DiscountStrategy strategy StrategyFactory.getStrategy(strategyKey); return strategy.calculatePrice(originalPrice); } } // 测试使用 public class FactoryStrategyTest { public static void main(String[] args) { FactoryStrategyContext context new FactoryStrategyContext(); BigDecimal result context.executePrice(eightDiscount, new BigDecimal(200)); System.out.println(优惠后价格 result); } }适用场景策略数量多、需要统一管理策略实例、客户端无需感知策略细节的中大型业务场景。优缺点职责拆分更清晰、屏蔽创建细节、支持策略缓存复用缺点是多了工厂类小幅增加代码量。2.4 Lambda匿名策略式轻量化极简特点基于Java8函数式接口特性无需定义策略实现类通过Lambda表达式动态实现策略逻辑适合简单、临时性策略。// 1. 函数式策略接口必须仅有一个抽象方法 FunctionalInterface public interface DiscountStrategy { BigDecimal calculatePrice(BigDecimal originalPrice); } // 2. 上下文类 public class LambdaStrategyContext { private DiscountStrategy discountStrategy; public void setDiscountStrategy(DiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } public BigDecimal executeCalculate(BigDecimal originalPrice) { return discountStrategy.calculatePrice(originalPrice); } } // 测试使用Lambda动态传入策略无需定义实现类 public class LambdaStrategyTest { public static void main(String[] args) { LambdaStrategyContext context new LambdaStrategyContext(); // 无优惠策略 context.setDiscountStrategy(price - price); System.out.println(无优惠价格 context.executeCalculate(new BigDecimal(200))); // 八折策略 context.setDiscountStrategy(price - price.multiply(new BigDecimal(0.8))); System.out.println(八折价格 context.executeCalculate(new BigDecimal(200))); // 满减策略 context.setDiscountStrategy(price - price.compareTo(new BigDecimal(100)) 0 ? price.subtract(new BigDecimal(20)) : price); System.out.println(满减价格 context.executeCalculate(new BigDecimal(200))); } }适用场景策略逻辑简单、临时动态定义、无需复用策略的场景快速简化分支代码。优缺点极致精简、无需创建大量实现类、灵活度高缺点是复杂策略逻辑会导致代码臃肿无法单独复用和单元测试。2.5 Spring容器策略式工程实战主流特点基于Spring IoC容器将所有策略实现类交给Spring管理通过依赖注入、Map自动注入批量获取所有策略实现自动分发是实际项目中最常用的实现方式。// 1. 策略接口 public interface PayStrategy { // 支付方法 String pay(BigDecimal money); } // 2. 具体策略实现交给Spring管理 Component(wechatPay) public class WechatPayStrategy implements PayStrategy { Override public String pay(BigDecimal money) { return 微信支付成功支付金额 money; } } Component(aliPay) public class AliPayStrategy implements PayStrategy { Override public String pay(BigDecimal money) { return 支付宝支付成功支付金额 money; } } Component(bankPay) public class BankPayStrategy implements PayStrategy { Override public String pay(BigDecimal money) { return 银行卡支付成功支付金额 money; } } // 3. 策略上下文/调度器Spring自动注入所有策略 Component public class PayStrategyContext { // 自动注入所有PayStrategy实现类key为组件名称value为策略实例 Autowired private MapString, PayStrategy payStrategyMap; // 根据支付类型获取策略并执行 public String executePay(String payType, BigDecimal money) { PayStrategy strategy payStrategyMap.get(payType); if (strategy null) { throw new IllegalArgumentException(不支持的支付方式); } return strategy.pay(money); } } // 测试Spring环境 SpringBootTest public class SpringStrategyTest { Autowired private PayStrategyContext payStrategyContext; Test public void testPay() { System.out.println(payStrategyContext.executePay(wechatPay, new BigDecimal(99.9))); System.out.println(payStrategyContext.executePay(aliPay, new BigDecimal(199.9))); } }适用场景SpringBoot/Spring工程、企业级业务开发、需要频繁扩展策略、需要统一管理策略实例的场景。优缺点无需手动创建管理策略、新增策略只需新增实现类即可完全开闭、适配业务迭代缺点是依赖Spring容器非原生Java实现。2.6 五种实现方式对比表实现方式开闭扩展性是否类爆炸代码简洁度依赖环境适用场景基础接口实现式优秀是中等原生Java通用业务、需要动态切换策略枚举策略式一般否高原生Java策略固定、数量少、无需频繁扩展工厂策略整合式优秀是中等原生Java多策略统一管理、屏蔽创建细节Lambda匿名策略式差否极高JDK8简单临时策略、快速简化分支代码Spring容器策略式极佳可控高Spring环境企业级项目、长期迭代扩展业务注类爆炸问题可通过分包管理strategy/impl优化Spring策略式虽有多个实现类但符合业务分层规范是工程中最优解简单场景无需过度封装优先选择轻量化实现。2.7 高级拓展组合策略多策略叠加执行业务中常需要多个策略叠加生效满减后再打折通过组合类统一串联执行所有策略// 策略组合器 public class CombinedDiscountStrategy implements DiscountStrategy { private final ListDiscountStrategy strategies; public CombinedDiscountStrategy(DiscountStrategy... strategies) { this.strategies Arrays.asList(strategies); } Override public double applyDiscount(double originalPrice) { double currentPrice originalPrice; //模拟写法生产上肯定会有更复杂的组合关系 for (DiscountStrategy strategy : strategies) { currentPrice strategy.applyDiscount(currentPrice); } return currentPrice; } } // 使用满300减50再9折 DiscountStrategy combined new CombinedDiscountStrategy( new FullReductionStrategy(300, 50), new PercentageDiscountStrategy(0.1) );2.8 拓展案例文件加密策略// 策略接口 public interface EncryptionStrategy { String encrypt(String content); String decrypt(String encryptedContent); } // AES加密策略 public class AesEncryptionStrategy implements EncryptionStrategy {} // RSA加密策略 public class RsaEncryptionStrategy implements EncryptionStrategy {} // 上下文 public class FileEncryptor { private EncryptionStrategy strategy; public FileEncryptor(EncryptionStrategy strategy) { this.strategy strategy; } public void encryptFile(String inputPath, String outputPath) { String content readFile(inputPath); String encrypted strategy.encrypt(content); writeFile(outputPath, encrypted); } }2.9 策略模式UML结构图_________________________ | Strategy | |------------------------| | executeAlgorithm() | |________________________| ▲ ____________|_____________ | | | ______▼______ ____▼______ _____▼______ | Concrete | | Concrete | | Concrete | | StrategyA | | StrategyB | | StrategyC | |___________| |___________| |___________| ▲ | _____▼_____ | Context | |-----------| | - strategy| |___________|2.10 JDK标准库原生策略模式落地面试高频Comparator比较器ListInteger numbers Arrays.asList(3, 1, 4, 1, 5); Collections.sort(numbers, Comparator.naturalOrder()); // 升序策略 Collections.sort(numbers, Comparator.reverseOrder()); // 降序策略ThreadPoolExecutor线程池拒绝策略ThreadPoolExecutor executor new ThreadPoolExecutor( 2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(10), new ThreadPoolExecutor.AbortPolicy() // 可切换Discard/CallerRuns等策略 );2.11 相似设计模式核心区分表模式核心区别工厂模式关注对象创建策略模式关注算法行为选择与替换命令模式封装单次操作请求支持撤销、排队策略模式封装可复用完整算法状态模式内部状态自动流转切换策略模式需要客户端显式指定切换算法3. 策略模式核心痛点与解决办法3.1 策略类过多类爆炸问题描述业务策略繁多时基础实现式会产生大量策略实现类项目结构臃肿不利于管理。解决方案1.简单固定策略使用枚举策略式统一收拢所有策略无需拆分独立类2.简单动态策略使用Lambda表达式动态定义省去实现类3.复杂多策略通过分包管理将策略实现类统一放入strategy/impl包规范项目结构。3.2 策略分发硬编码问题描述传统写法中客户端通过硬编码key、分支判断获取策略新增策略需要修改分发代码违反开闭原则。解决方案1.原生场景使用工厂模式缓存Map统一分发无需修改核心代码2.Spring场景利用Spring自动注入Map新增策略只需新增实现类自动注册生效3.统一策略编码规范通过配置文件、枚举映射策略key彻底消除硬编码。3.3 空策略、未知策略容错问题描述传入不存在的策略key会出现空指针、未知异常程序健壮性差。解决方案1. 策略获取时增加非空判断兜底返回默认策略2.自定义业务异常替换原生空指针异常统一异常提示3. 枚举策略通过code遍历匹配无匹配时抛出明确异常。3.4 策略重复创建、性能冗余问题描述每次调用策略都新建对象频繁调用会产生大量临时对象造成GC压力。解决方案1. 原生场景通过静态Map缓存所有策略实例全局复用2. Spring场景利用Spring单例特性策略类默认单例托管无需手动缓存3. 无状态策略天然可复用禁止每次调用new新对象。4. 总结策略模式的核心是解耦分支算法、拥抱开闭原则、实现算法可替换规避臃肿的if-else代码选择实现方式需结合业务场景1.企业Spring项目首选Spring容器策略式扩展性最强、适配业务迭代、无需手动管理实例2.固定少量策略选枚举式代码简洁、无类爆炸、统一管理3.简单临时策略选Lambda式极致精简快速优化分支代码4.原生Java通用场景选基础/工厂策略式结构标准、通用性强5.坚决避免过度设计少量固定分支、无扩展需求的场景无需强行使用策略模式。理解策略模式的核心思想而非死记代码才能在复杂业务中彻底消灭分支嵌套写出高扩展、高维护、高复用的业务代码。
设计模式-策略模式精讲
发布时间:2026/7/1 18:39:32
如下是本文目录1. 为什么需要策略模式1.1 使用策略模式要解决的核心痛点1.2 正确典型使用场景1.3 不适合策略模式的场景2. 五种常见实现方式2.1 基础接口实现式原生标准2.2 枚举策略式极简无类爆炸2.3 工厂策略整合式解耦增强2.4 Lambda匿名策略式轻量化极简2.5 Spring容器策略式工程实战主流2.6 五种实现方式对比表2.7 高级拓展组合策略多策略叠加执行2.8 拓展案例文件加密策略2.9 策略模式UML结构图2.10 JDK标准库原生策略模式落地面试高频2.11 相似设计模式核心区分表3. 策略模式核心痛点与解决办法3.1 策略类过多类爆炸3.2 策略分发硬编码3.3 空策略、未知策略容错3.4 策略重复创建、性能冗余4. 总结1. 为什么需要策略模式策略模式是行为型设计模式核心目标定义一系列独立的算法业务策略将每个算法封装为独立类让算法可以互相替换且算法的变化不会影响调用算法的客户端完美实现业务算法与业务调用逻辑的解耦。换句话讲策略模式就是把多变的业务算法单独封装成一个个可替换的独立类外部调用代码只负责调度不需要关心算法内部细节换算法不用改主流程实现算法和业务代码解绑。1.1 使用策略模式要解决的核心痛点a. 业务中大量分支判断if-else/switch随着策略增多代码臃肿冗长、维护成本极高b. 算法逻辑高度耦合在业务主类中修改、新增算法需要改动核心业务代码违反开闭原则c. 不同业务算法逻辑混杂代码可读性差容易出现分支逻辑冲突、修改牵一发而动全身的问题d. 算法无法独立复用、单独测试多场景复用相同算法需要重复编码。1.2 正确典型使用场景a.多条件分支业务计算订单支付方式微信/支付宝/银行卡、折扣计算满减/折扣/优惠券、运费计算b.多类型数据处理策略文件解析Excel/Word/PDF、消息推送短信/邮件/APP推送、日志输出控制台/文件/数据库c.业务规则动态切换会员等级权益计算、风控校验规则、排序筛选策略、汇率换算策略d.框架层级算法替换线程池拒绝策略、Spring资源加载策略、序列化策略、缓存淘汰策略。1.3 不适合策略模式的场景a.策略极少变动、分支固定仅1-2个固定分支业务终身不会新增策略使用if-else更简洁b.算法逻辑极其简单单句代码即可实现的分支逻辑拆分策略类会造成类爆炸、过度设计c.策略之间存在强依赖、无法独立拆分多个算法逻辑耦合绑定拆分后会增加代码复杂度d.临时一次性业务策略无需复用、无需扩展的临时分支逻辑无需封装策略。2. 五种常见实现方式策略模式三大标准核心角色a.Strategy策略接口定义所有算法统一公共规范对外暴露统一执行方法b.ConcreteStrategy具体策略实现类独立实现接口封装单一算法逻辑单一职责c.Context上下文调度类持有策略对象引用提供动态修改策略入口接收客户端请求并委托策略执行。2.1 基础接口实现式原生标准特点定义统一策略接口不同策略实现接口上下文类持有策略对象对外提供统一调用入口是最经典、最标准的策略模式实现。// 1. 统一策略接口定义算法规范 public interface DiscountStrategy { // 计算折扣后价格 BigDecimal calculatePrice(BigDecimal originalPrice); } // 2. 具体策略实现1无优惠 public class NoDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice; } } // 3. 具体策略实现2八折优惠 public class EightDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.multiply(new BigDecimal(0.8)); } } // 4. 具体策略实现3满减优惠 public class FullReductionStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { // 满100减20 return originalPrice.compareTo(new BigDecimal(100)) 0 ? originalPrice.subtract(new BigDecimal(20)) : originalPrice; } } // 5. 上下文类统一调度入口持有策略 public class DiscountContext { // 持有策略接口引用运行时通过传入不同实现类来切换优惠算法 这也是JAVA中多态的核心运用 private DiscountStrategy discountStrategy; // 注入策略 public DiscountContext(DiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } // 动态修改策略 public void setDiscountStrategy(DiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } // 对外统一调用方法 public BigDecimal executeCalculate(BigDecimal originalPrice) { return discountStrategy.calculatePrice(originalPrice); } } // 测试使用 public class StrategyTest { public static void main(String[] args) { DiscountContext context new DiscountContext(new EightDiscountStrategy()); System.out.println(八折后价格 context.executeCalculate(new BigDecimal(200))); // 动态切换策略 context.setDiscountStrategy(new FullReductionStrategy()); System.out.println(满减后价格 context.executeCalculate(new BigDecimal(200))); } }适用场景策略数量适中、需要动态切换策略、常规业务解耦场景是企业开发通用首选。优缺点结构清晰、完全符合开闭原则、策略可独立扩展缺点是策略较多时会产生大量独立策略类。2.2 枚举策略式极简无类爆炸特点将所有策略封装在枚举内部通过枚举常量区分不同策略整合策略定义、实现、分发无需创建大量独立实现类代码极简。// 枚举策略整合所有折扣算法 public enum DiscountEnumStrategy { // 枚举常量对应不同策略 NO_DISCOUNT(1, 无优惠) { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice; } }, EIGHT_DISCOUNT(2, 八折优惠) { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.multiply(new BigDecimal(0.8)); } }, FULL_REDUCTION(3, 满减优惠) { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.compareTo(new BigDecimal(100)) 0 ? originalPrice.subtract(new BigDecimal(20)) : originalPrice; } }; // 策略编码、描述 private final int code; private final String desc; DiscountEnumStrategy(int code, String desc) { this.code code; this.desc desc; } // 抽象策略方法由每个枚举常量实现 public abstract BigDecimal calculatePrice(BigDecimal originalPrice); // 根据code获取对应策略 public static DiscountEnumStrategy getStrategyByCode(int code) { for (DiscountEnumStrategy strategy : values()) { if (strategy.code code) { return strategy; } } throw new IllegalArgumentException(无效的优惠策略编码); } // getter方法 public int getCode() { return code; } public String getDesc() { return desc; } } // 测试使用 public class EnumStrategyTest { public static void main(String[] args) { // 根据编码获取策略并执行 DiscountEnumStrategy strategy DiscountEnumStrategy.getStrategyByCode(2); System.out.println(strategy.getDesc() 价格 strategy.calculatePrice(new BigDecimal(200))); } }适用场景策略固定、不会频繁新增策略数量可控的业务场景替代大量简单策略类。优缺点杜绝类爆炸、代码集中统一管理、调用简洁缺点是策略逻辑复杂时枚举类会过于臃肿不适合复杂算法。2.3 工厂策略整合式解耦增强特点结合简单工厂模式新增策略工厂类统一创建、分发策略对象彻底屏蔽策略创建细节客户端无需感知具体策略实现类进一步解耦。// 1. 策略接口同基础实现 public interface DiscountStrategy { BigDecimal calculatePrice(BigDecimal originalPrice); } // 2. 具体策略实现 public class NoDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice; } } public class EightDiscountStrategy implements DiscountStrategy { Override public BigDecimal calculatePrice(BigDecimal originalPrice) { return originalPrice.multiply(new BigDecimal(0.8)); } } // 3. 策略工厂类统一生产策略 public class StrategyFactory { // 缓存所有策略避免重复创建 private static final MapString, DiscountStrategy STRATEGY_CACHE new HashMap(); // 静态初始化所有策略 static { STRATEGY_CACHE.put(noDiscount, new NoDiscountStrategy()); STRATEGY_CACHE.put(eightDiscount, new EightDiscountStrategy()); } // 根据key获取策略 public static DiscountStrategy getStrategy(String strategyKey) { DiscountStrategy strategy STRATEGY_CACHE.get(strategyKey); if (strategy null) { throw new IllegalArgumentException(不存在该优惠策略); } return strategy; } } // 4. 上下文调用 public class FactoryStrategyContext { public BigDecimal executePrice(String strategyKey, BigDecimal originalPrice) { // 工厂获取策略直接执行 DiscountStrategy strategy StrategyFactory.getStrategy(strategyKey); return strategy.calculatePrice(originalPrice); } } // 测试使用 public class FactoryStrategyTest { public static void main(String[] args) { FactoryStrategyContext context new FactoryStrategyContext(); BigDecimal result context.executePrice(eightDiscount, new BigDecimal(200)); System.out.println(优惠后价格 result); } }适用场景策略数量多、需要统一管理策略实例、客户端无需感知策略细节的中大型业务场景。优缺点职责拆分更清晰、屏蔽创建细节、支持策略缓存复用缺点是多了工厂类小幅增加代码量。2.4 Lambda匿名策略式轻量化极简特点基于Java8函数式接口特性无需定义策略实现类通过Lambda表达式动态实现策略逻辑适合简单、临时性策略。// 1. 函数式策略接口必须仅有一个抽象方法 FunctionalInterface public interface DiscountStrategy { BigDecimal calculatePrice(BigDecimal originalPrice); } // 2. 上下文类 public class LambdaStrategyContext { private DiscountStrategy discountStrategy; public void setDiscountStrategy(DiscountStrategy discountStrategy) { this.discountStrategy discountStrategy; } public BigDecimal executeCalculate(BigDecimal originalPrice) { return discountStrategy.calculatePrice(originalPrice); } } // 测试使用Lambda动态传入策略无需定义实现类 public class LambdaStrategyTest { public static void main(String[] args) { LambdaStrategyContext context new LambdaStrategyContext(); // 无优惠策略 context.setDiscountStrategy(price - price); System.out.println(无优惠价格 context.executeCalculate(new BigDecimal(200))); // 八折策略 context.setDiscountStrategy(price - price.multiply(new BigDecimal(0.8))); System.out.println(八折价格 context.executeCalculate(new BigDecimal(200))); // 满减策略 context.setDiscountStrategy(price - price.compareTo(new BigDecimal(100)) 0 ? price.subtract(new BigDecimal(20)) : price); System.out.println(满减价格 context.executeCalculate(new BigDecimal(200))); } }适用场景策略逻辑简单、临时动态定义、无需复用策略的场景快速简化分支代码。优缺点极致精简、无需创建大量实现类、灵活度高缺点是复杂策略逻辑会导致代码臃肿无法单独复用和单元测试。2.5 Spring容器策略式工程实战主流特点基于Spring IoC容器将所有策略实现类交给Spring管理通过依赖注入、Map自动注入批量获取所有策略实现自动分发是实际项目中最常用的实现方式。// 1. 策略接口 public interface PayStrategy { // 支付方法 String pay(BigDecimal money); } // 2. 具体策略实现交给Spring管理 Component(wechatPay) public class WechatPayStrategy implements PayStrategy { Override public String pay(BigDecimal money) { return 微信支付成功支付金额 money; } } Component(aliPay) public class AliPayStrategy implements PayStrategy { Override public String pay(BigDecimal money) { return 支付宝支付成功支付金额 money; } } Component(bankPay) public class BankPayStrategy implements PayStrategy { Override public String pay(BigDecimal money) { return 银行卡支付成功支付金额 money; } } // 3. 策略上下文/调度器Spring自动注入所有策略 Component public class PayStrategyContext { // 自动注入所有PayStrategy实现类key为组件名称value为策略实例 Autowired private MapString, PayStrategy payStrategyMap; // 根据支付类型获取策略并执行 public String executePay(String payType, BigDecimal money) { PayStrategy strategy payStrategyMap.get(payType); if (strategy null) { throw new IllegalArgumentException(不支持的支付方式); } return strategy.pay(money); } } // 测试Spring环境 SpringBootTest public class SpringStrategyTest { Autowired private PayStrategyContext payStrategyContext; Test public void testPay() { System.out.println(payStrategyContext.executePay(wechatPay, new BigDecimal(99.9))); System.out.println(payStrategyContext.executePay(aliPay, new BigDecimal(199.9))); } }适用场景SpringBoot/Spring工程、企业级业务开发、需要频繁扩展策略、需要统一管理策略实例的场景。优缺点无需手动创建管理策略、新增策略只需新增实现类即可完全开闭、适配业务迭代缺点是依赖Spring容器非原生Java实现。2.6 五种实现方式对比表实现方式开闭扩展性是否类爆炸代码简洁度依赖环境适用场景基础接口实现式优秀是中等原生Java通用业务、需要动态切换策略枚举策略式一般否高原生Java策略固定、数量少、无需频繁扩展工厂策略整合式优秀是中等原生Java多策略统一管理、屏蔽创建细节Lambda匿名策略式差否极高JDK8简单临时策略、快速简化分支代码Spring容器策略式极佳可控高Spring环境企业级项目、长期迭代扩展业务注类爆炸问题可通过分包管理strategy/impl优化Spring策略式虽有多个实现类但符合业务分层规范是工程中最优解简单场景无需过度封装优先选择轻量化实现。2.7 高级拓展组合策略多策略叠加执行业务中常需要多个策略叠加生效满减后再打折通过组合类统一串联执行所有策略// 策略组合器 public class CombinedDiscountStrategy implements DiscountStrategy { private final ListDiscountStrategy strategies; public CombinedDiscountStrategy(DiscountStrategy... strategies) { this.strategies Arrays.asList(strategies); } Override public double applyDiscount(double originalPrice) { double currentPrice originalPrice; //模拟写法生产上肯定会有更复杂的组合关系 for (DiscountStrategy strategy : strategies) { currentPrice strategy.applyDiscount(currentPrice); } return currentPrice; } } // 使用满300减50再9折 DiscountStrategy combined new CombinedDiscountStrategy( new FullReductionStrategy(300, 50), new PercentageDiscountStrategy(0.1) );2.8 拓展案例文件加密策略// 策略接口 public interface EncryptionStrategy { String encrypt(String content); String decrypt(String encryptedContent); } // AES加密策略 public class AesEncryptionStrategy implements EncryptionStrategy {} // RSA加密策略 public class RsaEncryptionStrategy implements EncryptionStrategy {} // 上下文 public class FileEncryptor { private EncryptionStrategy strategy; public FileEncryptor(EncryptionStrategy strategy) { this.strategy strategy; } public void encryptFile(String inputPath, String outputPath) { String content readFile(inputPath); String encrypted strategy.encrypt(content); writeFile(outputPath, encrypted); } }2.9 策略模式UML结构图_________________________ | Strategy | |------------------------| | executeAlgorithm() | |________________________| ▲ ____________|_____________ | | | ______▼______ ____▼______ _____▼______ | Concrete | | Concrete | | Concrete | | StrategyA | | StrategyB | | StrategyC | |___________| |___________| |___________| ▲ | _____▼_____ | Context | |-----------| | - strategy| |___________|2.10 JDK标准库原生策略模式落地面试高频Comparator比较器ListInteger numbers Arrays.asList(3, 1, 4, 1, 5); Collections.sort(numbers, Comparator.naturalOrder()); // 升序策略 Collections.sort(numbers, Comparator.reverseOrder()); // 降序策略ThreadPoolExecutor线程池拒绝策略ThreadPoolExecutor executor new ThreadPoolExecutor( 2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(10), new ThreadPoolExecutor.AbortPolicy() // 可切换Discard/CallerRuns等策略 );2.11 相似设计模式核心区分表模式核心区别工厂模式关注对象创建策略模式关注算法行为选择与替换命令模式封装单次操作请求支持撤销、排队策略模式封装可复用完整算法状态模式内部状态自动流转切换策略模式需要客户端显式指定切换算法3. 策略模式核心痛点与解决办法3.1 策略类过多类爆炸问题描述业务策略繁多时基础实现式会产生大量策略实现类项目结构臃肿不利于管理。解决方案1.简单固定策略使用枚举策略式统一收拢所有策略无需拆分独立类2.简单动态策略使用Lambda表达式动态定义省去实现类3.复杂多策略通过分包管理将策略实现类统一放入strategy/impl包规范项目结构。3.2 策略分发硬编码问题描述传统写法中客户端通过硬编码key、分支判断获取策略新增策略需要修改分发代码违反开闭原则。解决方案1.原生场景使用工厂模式缓存Map统一分发无需修改核心代码2.Spring场景利用Spring自动注入Map新增策略只需新增实现类自动注册生效3.统一策略编码规范通过配置文件、枚举映射策略key彻底消除硬编码。3.3 空策略、未知策略容错问题描述传入不存在的策略key会出现空指针、未知异常程序健壮性差。解决方案1. 策略获取时增加非空判断兜底返回默认策略2.自定义业务异常替换原生空指针异常统一异常提示3. 枚举策略通过code遍历匹配无匹配时抛出明确异常。3.4 策略重复创建、性能冗余问题描述每次调用策略都新建对象频繁调用会产生大量临时对象造成GC压力。解决方案1. 原生场景通过静态Map缓存所有策略实例全局复用2. Spring场景利用Spring单例特性策略类默认单例托管无需手动缓存3. 无状态策略天然可复用禁止每次调用new新对象。4. 总结策略模式的核心是解耦分支算法、拥抱开闭原则、实现算法可替换规避臃肿的if-else代码选择实现方式需结合业务场景1.企业Spring项目首选Spring容器策略式扩展性最强、适配业务迭代、无需手动管理实例2.固定少量策略选枚举式代码简洁、无类爆炸、统一管理3.简单临时策略选Lambda式极致精简快速优化分支代码4.原生Java通用场景选基础/工厂策略式结构标准、通用性强5.坚决避免过度设计少量固定分支、无扩展需求的场景无需强行使用策略模式。理解策略模式的核心思想而非死记代码才能在复杂业务中彻底消灭分支嵌套写出高扩展、高维护、高复用的业务代码。