1. 策略模式初探从菜鸟到高手的必经之路记得刚入行Java开发那会儿我接手了一个电商促销模块的需求。产品经理拿着需求文档说我们需要支持满减、折扣、赠品三种促销方式而且后期可能还会增加新的类型。当时的我二话不说就写了三个if-else分支结果两个月后新增了五种促销策略代码变成了意大利面条——这就是我初次遭遇策略模式应用场景的惨痛教训。策略模式Strategy Pattern作为GoF 23种设计模式中最常用的行为型模式之一其核心思想是将算法家族分别封装起来让它们之间可以互相替换。这种模式让算法的变化独立于使用算法的客户完美解决了我在电商项目中遇到的痛点。在实际开发中凡是遇到需要根据不同条件执行不同业务逻辑的场景比如支付方式选择、文件解析策略、数据压缩算法等策略模式都能大显身手。关键认知策略模式不是简单的if-else替代品而是通过面向接口编程实现运行时动态切换行为的能力这是它与状态模式最本质的区别。2. 策略模式的骨骼解剖UML与代码实现2.1 标准UML结构解析先来看策略模式的经典UML类图文字描述版Context环境类持有一个Strategy的引用通过构造函数或setter注入具体策略Strategy抽象策略定义所有支持的算法的公共接口通常为接口或抽象类ConcreteStrategy具体策略实现Strategy接口的具体算法类// 抽象策略接口 public interface PromotionStrategy { BigDecimal applyPromotion(BigDecimal price); } // 具体策略实现 public class FullReductionStrategy implements PromotionStrategy { Override public BigDecimal applyPromotion(BigDecimal price) { return price.compareTo(100) 0 ? price.subtract(20) : price; } } public class DiscountStrategy implements PromotionStrategy { Override public BigDecimal applyPromotion(BigDecimal price) { return price.multiply(new BigDecimal(0.8)); } } // 环境上下文 public class PromotionContext { private PromotionStrategy strategy; public PromotionContext(PromotionStrategy strategy) { this.strategy strategy; } public BigDecimal executeStrategy(BigDecimal price) { return strategy.applyPromotion(price); } }2.2 Java 8后的优雅实现自从Java 8引入函数式编程特性后策略模式有了更简洁的实现方式public class PromotionContext { private FunctionBigDecimal, BigDecimal strategy; public PromotionContext(FunctionBigDecimal, BigDecimal strategy) { this.strategy strategy; } public BigDecimal applyPromotion(BigDecimal price) { return strategy.apply(price); } } // 使用示例 PromotionContext fullReduction new PromotionContext( price - price.compareTo(100) 0 ? price.subtract(20) : price );这种实现方式减少了类的爆炸特别适合简单策略场景。但要注意当策略逻辑复杂需要维护状态时还是应该使用传统的类实现方式。3. 策略模式的实战进阶技巧3.1 策略工厂的三种实现范式在实际项目中我们通常需要根据类型标识创建具体策略。以下是三种常见的策略工厂实现简单工厂模式public class StrategyFactory { public static PromotionStrategy getStrategy(String type) { switch(type) { case FULL_REDUCTION: return new FullReductionStrategy(); case DISCOUNT: return new DiscountStrategy(); default: throw new IllegalArgumentException(); } } }枚举工厂推荐public enum StrategyEnum { FULL_REDUCTION(new FullReductionStrategy()), DISCOUNT(new DiscountStrategy()); private PromotionStrategy strategy; StrategyEnum(PromotionStrategy strategy) { this.strategy strategy; } public PromotionStrategy getStrategy() { return strategy; } }Spring容器工厂企业级方案Component public class StrategySpringFactory { Autowired private MapString, PromotionStrategy strategyMap; public PromotionStrategy getStrategy(String type) { return strategyMap.get(type Strategy); } } // 策略实现类需添加Component注解如 Component(fullReductionStrategy) public class FullReductionStrategy implements PromotionStrategy {...}3.2 策略模式与Spring的完美融合在企业级应用中结合Spring框架可以实现更优雅的策略模式// 定义策略注解 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Component public interface StrategyType { String value(); } // 注解式策略实现 StrategyType(fullReduction) public class FullReductionStrategy implements PromotionStrategy {...} // 策略上下文自动装配 Service public class PromotionService { Autowired private MapString, PromotionStrategy strategyMap; public BigDecimal applyPromotion(String type, BigDecimal price) { PromotionStrategy strategy strategyMap.values().stream() .filter(s - s.getClass().getAnnotation(StrategyType.class).value().equals(type)) .findFirst() .orElseThrow(); return strategy.applyPromotion(price); } }这种实现方式通过注解自动注册策略避免了手动维护策略映射表新增策略只需添加新的实现类并标注注解即可。4. 策略模式的深度应用与陷阱规避4.1 策略组合模式复杂业务场景中我们可能需要组合多个策略。比如电商促销可能同时满足满减和折扣条件public class CompositePromotionStrategy implements PromotionStrategy { private ListPromotionStrategy strategies; public CompositePromotionStrategy(ListPromotionStrategy strategies) { this.strategies strategies; } Override public BigDecimal applyPromotion(BigDecimal price) { BigDecimal result price; for (PromotionStrategy strategy : strategies) { result strategy.applyPromotion(result); } return result; } }4.2 常见陷阱与解决方案策略膨胀问题现象策略类过多导致维护困难方案使用策略模板方法模式将公共逻辑提取到抽象类中策略状态管理现象策略需要维护状态导致线程安全问题方案采用无状态设计或将状态封装到Context中策略选择复杂度现象策略选择逻辑过于复杂方案引入责任链模式构建策略选择流水线// 策略选择责任链示例 public interface StrategySelector { boolean canHandle(String type); PromotionStrategy select(); } public class FullReductionSelector implements StrategySelector { Override public boolean canHandle(String type) { return FULL_REDUCTION.equals(type); } Override public PromotionStrategy select() { return new FullReductionStrategy(); } } public class StrategySelectionChain { private ListStrategySelector selectors; public PromotionStrategy selectStrategy(String type) { return selectors.stream() .filter(s - s.canHandle(type)) .findFirst() .map(StrategySelector::select) .orElseThrow(); } }4.3 性能优化技巧策略对象复用无状态策略可使用单例模式有状态策略考虑对象池技术策略缓存机制public class StrategyCache { private static final MapString, PromotionStrategy cache new ConcurrentHashMap(); public static PromotionStrategy getStrategy(String type) { return cache.computeIfAbsent(type, k - { // 创建策略的逻辑 }); } }并行策略处理public BigDecimal applyParallelStrategies(ListPromotionStrategy strategies, BigDecimal price) { return strategies.parallelStream() .reduce(price, (p, s) - s.applyPromotion(p), BigDecimal::add); }5. 策略模式在开源框架中的经典应用5.1 JDK中的策略模式Comparator接口Collections.sort(list, (o1, o2) - o1.getPrice().compareTo(o2.getPrice()));排序策略可以动态指定ThreadPoolExecutor的拒绝策略new ThreadPoolExecutor(..., new ThreadPoolExecutor.AbortPolicy());内置四种拒绝策略AbortPolicy、CallerRunsPolicy等5.2 Spring框架中的策略应用ResourceLoader根据资源路径前缀选择不同的资源加载策略classpath:、file:、http:等前缀对应不同策略HandlerMapping多种URL到处理器的映射策略BeanNameUrlHandlerMapping、RequestMappingHandlerMapping等5.3 企业级项目实战案例电商支付系统设计public interface PaymentStrategy { PaymentResult pay(PaymentRequest request); } StrategyType(ALIPAY) public class AlipayStrategy implements PaymentStrategy {...} StrategyType(WECHAT) public class WechatPayStrategy implements PaymentStrategy {...} Service public class PaymentService { Autowired private MapString, PaymentStrategy strategies; public PaymentResult processPayment(String channel, PaymentRequest request) { PaymentStrategy strategy strategies.get(channel Strategy); if (strategy null) { throw new UnsupportedPaymentChannelException(); } return strategy.pay(request); } }日志处理系统设计public interface LogExportStrategy { void export(ListLogEntry logs); } StrategyType(CSV) public class CsvExportStrategy implements LogExportStrategy {...} StrategyType(JSON) public class JsonExportStrategy implements LogExportStrategy {...} public class LogExporter { private LogExportStrategy strategy; public void setStrategy(LogExportStrategy strategy) { this.strategy strategy; } public void exportLogs(ListLogEntry logs) { strategy.export(logs); } }6. 策略模式面试深度剖析6.1 高频面试题解析策略模式与状态模式的区别策略模式客户端主动选择策略策略之间独立无关状态模式状态自动转换状态之间知道彼此的存在策略模式如何避免if-else通过多态调用替代条件判断结合工厂模式自动创建策略策略模式的优缺点优点开闭原则、避免多重条件判断、算法可复用缺点客户端必须了解所有策略、策略类数量可能爆炸6.2 设计题实战优惠券系统设计题目设计一个支持多种优惠券类型满减、折扣、立减的系统要求方便扩展新类型参考实现// 定义优惠券策略接口 public interface CouponStrategy { BigDecimal apply(BigDecimal price, Coupon coupon); } // 具体策略实现 public class FullReductionCouponStrategy implements CouponStrategy { Override public BigDecimal apply(BigDecimal price, Coupon coupon) { return price.compareTo(coupon.getCondition()) 0 ? price.subtract(coupon.getBenefit()) : price; } } // 优惠券上下文 public class CouponContext { private static final MapCouponType, CouponStrategy strategies Map.of( CouponType.FULL_REDUCTION, new FullReductionCouponStrategy(), CouponType.DISCOUNT, new DiscountCouponStrategy() ); public BigDecimal applyCoupon(BigDecimal price, Coupon coupon) { return strategies.get(coupon.getType()).apply(price, coupon); } }6.3 性能优化追问面试官可能会问当策略判断非常频繁时比如每秒百万次如何优化策略模式的性能优化方案使用枚举策略实现利用JVM的静态绑定优化策略对象预初始化缓存对于简单策略可以用switch代替多态考虑策略的并行处理能力// 高性能策略枚举实现 public enum HighPerformanceStrategy implements PromotionStrategy { FULL_REDUCTION { Override public BigDecimal applyPromotion(BigDecimal price) { return price.compareTo(100) 0 ? price.subtract(20) : price; } }, DISCOUNT { Override public BigDecimal applyPromotion(BigDecimal price) { return price.multiply(new BigDecimal(0.8)); } }; } // 使用示例 BigDecimal result HighPerformanceStrategy.valueOf(type).applyPromotion(price);7. 策略模式的现代演进与替代方案7.1 函数式编程的冲击Java 8引入的Lambda和方法引用为策略模式提供了新的实现思路public class ModernStrategyContext { private final MapString, FunctionBigDecimal, BigDecimal strategies Map.of( FULL_REDUCTION, price - price.compareTo(100) 0 ? price.subtract(20) : price, DISCOUNT, price - price.multiply(new BigDecimal(0.8)) ); public BigDecimal apply(String type, BigDecimal price) { return strategies.get(type).apply(price); } }这种实现方式更加简洁但要注意适合简单策略场景复杂策略还是应该使用类实现缺乏明确的类型检查7.2 策略模式与Spring Cloud的碰撞在微服务架构中策略模式常被用于客户端负载均衡Configuration public class LoadBalanceConfiguration { Bean public ServiceInstanceChooser randomChooser() { return instances - instances.get(ThreadLocalRandom.current().nextInt(instances.size())); } Bean public ServiceInstanceChooser roundRobinChooser() { return new RoundRobinChooser(); } } Service public class LoadBalanceService { Autowired private MapString, ServiceInstanceChooser choosers; public ServiceInstance choose(String strategyName, ListServiceInstance instances) { return choosers.get(strategyName).choose(instances); } }7.3 策略模式的新形态云原生实现在Serverless架构中策略模式可以这样实现// AWS Lambda策略示例 public class PaymentHandler implements RequestHandlerPaymentRequest, PaymentResult { private final MapPaymentType, PaymentStrategy strategies; public PaymentHandler() { this.strategies Map.of( PaymentType.CREDIT, new CreditCardStrategy(), PaymentType.PAYPAL, new PayPalStrategy() ); } Override public PaymentResult handleRequest(PaymentRequest request, Context context) { return strategies.get(request.getType()).process(request); } }这种实现方式特别适合事件驱动的场景每个策略可以独立部署和扩展。8. 从策略模式看设计原则的落地8.1 SOLID原则的完美诠释策略模式是SOLID原则的经典体现单一职责原则每个策略类只负责一个算法开闭原则新增策略无需修改现有代码里氏替换原则所有策略实现可互相替换接口隔离原则策略接口保持最小化依赖倒置原则依赖抽象而非实现8.2 设计模式组合拳策略模式常与其他模式配合使用策略工厂模式动态创建策略策略组合模式构建策略树策略模板方法模式提取公共算法骨架策略装饰器模式动态添加策略功能// 策略装饰器示例 public class LoggingStrategyDecorator implements PromotionStrategy { private final PromotionStrategy delegate; public LoggingStrategyDecorator(PromotionStrategy delegate) { this.delegate delegate; } Override public BigDecimal applyPromotion(BigDecimal price) { System.out.println(Applying strategy: delegate.getClass().getSimpleName()); BigDecimal result delegate.applyPromotion(price); System.out.println(Original price: price , after promotion: result); return result; } }8.3 领域驱动设计中的策略模式在DDD中策略模式常被用于实现领域服务// 定价策略领域服务 public interface PricingStrategy { Money calculatePrice(Order order); } // 会员定价策略 public class MemberPricingStrategy implements PricingStrategy { Override public Money calculatePrice(Order order) { return order.getBasePrice().multiply(order.getMember().getDiscountRate()); } } // 定价上下文 Service public class PricingService { Autowired private MemberService memberService; public Money calculateFinalPrice(Order order) { PricingStrategy strategy memberService.isPremium(order.getCustomerId()) ? new MemberPricingStrategy() : new RegularPricingStrategy(); return strategy.calculatePrice(order); } }这种实现方式将业务规则封装在策略中保持了领域模型的纯净性。