Java策略模式实战:电商促销系统设计
1. 为什么策略模式是Java开发者的必备技能第一次接触策略模式是在我刚工作那年接手的一个电商促销系统。当时系统里有几十个if-else判断不同用户类型的折扣计算逻辑每次新增活动类型都要在原有代码上打补丁。直到我的导师指着那段300行的代码说这里该用策略模式了我才意识到设计模式不是教科书里的理论而是解决实际痛点的利器。策略模式Strategy Pattern属于行为型设计模式它定义了算法家族并分别封装起来让它们可以互相替换。这种模式让算法的变化独立于使用算法的客户端——就像给手机换APP不需要换手机本身。在Java开发中策略模式特别适合处理同一问题存在多种解决方案的场景如支付方式、排序算法需要动态切换算法行为的场景如游戏难度调整存在大量条件判断语句的场景如我遇到的那个促销系统提示当你发现自己在不断修改同一段代码来添加新行为时就是考虑策略模式的信号2. 策略模式的三大核心组件2.1 策略接口定义作战计划策略接口是模式中的宪法它用抽象方法规定了所有具体策略必须实现的操作。在Java中我们通常用接口定义public interface DiscountStrategy { double applyDiscount(double originalPrice); }这个简单的接口却蕴含了重要设计思想方法命名要体现业务语义applyDiscount比calculate更直观参数设计要足够通用原始价格而非订单对象降低耦合返回类型要明确避免用Object这类模糊类型2.2 具体策略类特种部队实现每个具体策略都是接口的一个实现像不同的特种部队// 普通会员策略 public class RegularMemberDiscount implements DiscountStrategy { Override public double applyDiscount(double originalPrice) { return originalPrice * 0.9; // 打9折 } } // VIP会员策略 public class VipMemberDiscount implements DiscountStrategy { Override public double applyDiscount(double originalPrice) { return originalPrice * 0.7; // 打7折 } }实际开发中容易踩的坑避免策略类持有状态应设计为无状态类策略逻辑应该纯粹不要混入业务校验等无关逻辑考虑线程安全性特别是使用了共享数据时2.3 上下文类战地指挥官Context类是使用策略的入口它有两个关键职责public class DiscountContext { private DiscountStrategy strategy; // 设置策略注入点 public void setStrategy(DiscountStrategy strategy) { this.strategy strategy; } // 执行策略 public double executeStrategy(double price) { if(strategy null) { throw new IllegalStateException(未设置折扣策略); } return strategy.applyDiscount(price); } }我在实际项目中总结的最佳实践上下文应该对客户端隐藏策略的创建细节可以结合工厂模式来管理策略实例添加合理的空策略检查如上面的异常抛出3. 从零实现策略模式的完整流程3.1 环境准备与基础搭建首先确保你的Java开发环境就绪JDK 8推荐JDK 11 LTS版本IDEIntelliJ IDEA或EclipseMaven/Gradle构建工具创建Maven项目的基本结构strategy-demo ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ ├── strategy │ │ │ └── Main.java │ │ └── resources │ └── test │ └── java3.2 完整代码实现示例我们用一个电商折扣系统来演示完整实现// 策略接口 public interface DiscountStrategy { String getType(); double applyDiscount(double originalPrice); } // 具体策略实现 public class NewUserDiscount implements DiscountStrategy { Override public String getType() { return NEW_USER; } Override public double applyDiscount(double price) { return price * 0.8; // 新用户8折 } } public class FestivalDiscount implements DiscountStrategy { Override public String getType() { return FESTIVAL; } Override public double applyDiscount(double price) { return price 100 ? price - 20 : price; // 满100减20 } } // 上下文类增强版 public class DiscountContext { private final MapString, DiscountStrategy strategies new HashMap(); public void addStrategy(DiscountStrategy strategy) { strategies.put(strategy.getType(), strategy); } public double applyDiscount(String type, double price) { DiscountStrategy strategy strategies.get(type); if(strategy null) { throw new IllegalArgumentException(无效的折扣类型: type); } return strategy.applyDiscount(price); } } // 客户端使用 public class Client { public static void main(String[] args) { DiscountContext context new DiscountContext(); context.addStrategy(new NewUserDiscount()); context.addStrategy(new FestivalDiscount()); double newUserPrice context.applyDiscount(NEW_USER, 200); System.out.println(新用户价格: newUserPrice); } }3.3 运行与测试在IDE中直接运行Client类你应该能看到输出新用户价格: 160.0进阶验证建议添加JUnit测试验证各种边界条件尝试添加新的折扣策略如季节性折扣测试传入无效策略类型时的处理4. 策略模式在Spring中的实战应用4.1 结合Spring的依赖注入在现代Java开发中我们通常会用Spring框架来管理策略Service public class DiscountService { private final MapString, DiscountStrategy strategies; Autowired public DiscountService(ListDiscountStrategy strategyList) { this.strategies strategyList.stream() .collect(Collectors.toMap( DiscountStrategy::getType, Function.identity() )); } public double applyDiscount(String type, double price) { DiscountStrategy strategy strategies.get(type); if(strategy null) { throw new IllegalArgumentException(不支持的折扣类型); } return strategy.applyDiscount(price); } }Spring会自动将所有实现DiscountStrategy的Bean注入到List中我们将其转换为Map方便查找。这种方式的好处是新增策略只需添加新的实现类不需要修改现有代码策略的创建由Spring容器管理4.2 策略模式与Spring Boot的完美结合在Spring Boot项目中我们可以做得更优雅定义策略接口public interface PaymentStrategy { String getType(); PaymentResult process(PaymentRequest request); }实现具体策略以支付宝支付为例Service public class AlipayStrategy implements PaymentStrategy { Override public String getType() { return ALIPAY; } Override public PaymentResult process(PaymentRequest request) { // 调用支付宝SDK的具体实现 return new PaymentResult(true, 支付宝支付成功); } }创建策略路由器Service public class PaymentRouter { private final MapString, PaymentStrategy strategies; public PaymentRouter(ListPaymentStrategy strategyList) { this.strategies strategyList.stream() .collect(Collectors.toMap( PaymentStrategy::getType, Function.identity() )); } public PaymentResult executePayment(String type, PaymentRequest request) { PaymentStrategy strategy strategies.get(type); if(strategy null) { throw new PaymentException(不支持的支付方式); } return strategy.process(request); } }在Controller中使用RestController RequestMapping(/payments) public class PaymentController { Autowired private PaymentRouter paymentRouter; PostMapping public ResponseEntity? pay(RequestBody PaymentRequest request) { try { PaymentResult result paymentRouter.executePayment( request.getPaymentType(), request ); return ResponseEntity.ok(result); } catch (PaymentException e) { return ResponseEntity.badRequest().body(e.getMessage()); } } }这种实现方式的优势完全符合开闭原则对扩展开放对修改关闭策略之间完全解耦便于单元测试新增支付方式只需添加新策略实现5. 策略模式的高级应用与性能优化5.1 策略模式的五种高级用法策略工厂模式集中管理策略实例的创建public class StrategyFactory { private static final MapString, DiscountStrategy STRATEGIES Map.of( VIP, new VipDiscount(), NEW, new NewUserDiscount() ); public static DiscountStrategy getStrategy(String type) { DiscountStrategy strategy STRATEGIES.get(type); if(strategy null) { throw new IllegalArgumentException(未知策略类型); } return strategy; } }策略模板方法模式在策略中复用公共逻辑public abstract class AbstractDiscount implements DiscountStrategy { // 公共前置处理 protected void beforeApply() { System.out.println(开始计算折扣...); } // 公共后置处理 protected void afterApply() { System.out.println(折扣计算完成); } Override public final double applyDiscount(double price) { beforeApply(); double result doApply(price); afterApply(); return result; } protected abstract double doApply(double price); }策略组合模式构建策略树处理复杂场景public class CompositeDiscount implements DiscountStrategy { private final ListDiscountStrategy strategies; public CompositeDiscount(ListDiscountStrategy strategies) { this.strategies strategies; } Override public double applyDiscount(double price) { double result price; for(DiscountStrategy strategy : strategies) { result strategy.applyDiscount(result); } return result; } }策略享元模式优化大量策略实例的性能public class StrategyFlyweight { private static final MapString, DiscountStrategy POOL new HashMap(); public static DiscountStrategy getStrategy(String type) { return POOL.computeIfAbsent(type, key - { switch(key) { case VIP: return new VipDiscount(); case NEW: return new NewUserDiscount(); default: throw new IllegalArgumentException(); } }); } }策略注解驱动更优雅的策略注册方式Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface StrategyType { String value(); } StrategyType(VIP) public class VipDiscount implements DiscountStrategy { // 实现代码 } // 在工厂类中扫描注解 public class AnnotationStrategyFactory { public static void registerStrategies(String packageName) { Reflections reflections new Reflections(packageName); SetClass? annotated reflections.getTypesAnnotatedWith(StrategyType.class); annotated.forEach(clazz - { StrategyType annotation clazz.getAnnotation(StrategyType.class); // 注册策略 }); } }5.2 策略模式的性能优化技巧策略对象的复用无状态策略可以设计为单例使用对象池管理有状态策略Spring中默认单例作用域足够应对大多数场景策略选择的优化// 使用枚举代替字符串查找 public enum DiscountType { VIP(new VipDiscount()), NEW(new NewUserDiscount()); private final DiscountStrategy strategy; DiscountType(DiscountStrategy strategy) { this.strategy strategy; } public DiscountStrategy getStrategy() { return strategy; } } // 使用方式 double discount DiscountType.VIP.getStrategy().applyDiscount(price);避免的策略模式误用策略类不宜过多超过20个考虑分类分层不要滥用策略模式处理简单条件分支策略接口不应过度膨胀遵循单一职责JMH性能测试示例BenchmarkMode(Mode.Throughput) OutputTimeUnit(TimeUnit.MILLISECONDS) public class StrategyBenchmark { State(Scope.Thread) public static class ExecutionPlan { public DiscountContext context new DiscountContext(); public double price 100.0; Setup public void setup() { context.addStrategy(new VipDiscount()); context.addStrategy(new NewUserDiscount()); } } Benchmark public double benchmarkVip(ExecutionPlan plan) { return plan.context.applyDiscount(VIP, plan.price); } }6. 策略模式在真实项目中的经典案例6.1 电商平台中的定价策略某大型电商平台的商品定价系统基础价格策略成本加成促销策略满减、折扣会员策略等级折扣地区策略区域定价组合策略多种策略叠加public class PriceCalculator { private final ListPricingStrategy strategies; public PriceCalculator(ListPricingStrategy strategies) { this.strategies strategies; } public BigDecimal calculate(Product product, User user) { BigDecimal price product.getBasePrice(); for(PricingStrategy strategy : strategies) { price strategy.apply(product, user, price); } return price; } }6.2 游戏开发中的AI行为策略一款RPG游戏中NPC的AI系统攻击策略近战、远程、魔法移动策略追击、逃跑、巡逻对话策略友好、敌对、中立public class NpcController { private CombatStrategy combatStrategy; private MovementStrategy movementStrategy; public void update(GameContext context) { movementStrategy.move(context); combatStrategy.attack(context); } // 根据游戏状态切换策略 public void adjustStrategies(GameState state) { if(state.isLowHealth()) { combatStrategy new DefensiveCombat(); movementStrategy new RetreatMovement(); } else { combatStrategy new AggressiveCombat(); movementStrategy new PatrolMovement(); } } }6.3 金融系统中的风控策略支付风控系统的策略实现基础风控策略金额限制、频次控制行为风控策略异常行为检测信用风控策略用户信用评估组合风控策略多策略联合决策public class RiskControlService { private final ListRiskStrategy strategies; public RiskResult check(PaymentRequest request) { RiskResult result new RiskResult(); for(RiskStrategy strategy : strategies) { strategy.evaluate(request, result); if(result.isBlocked()) { break; // 任一策略拦截则终止 } } return result; } }6.4 物流系统中的运费计算跨境电商的运费计算模块重量策略按重量计费体积策略按体积计费地区策略目的地运费系数快递策略不同快递公司报价促销策略包邮活动public class ShippingFeeCalculator { public BigDecimal calculate(Order order) { ShippingStrategy strategy determineMainStrategy(order); BigDecimal fee strategy.calculate(order); // 应用附加策略 for(ShippingDecorator decorator : decorators) { fee decorator.decorate(fee, order); } return fee; } private ShippingStrategy determineMainStrategy(Order order) { if(order.isOversized()) { return new VolumetricStrategy(); } return new WeightStrategy(); } }7. 策略模式常见问题与解决方案7.1 如何管理策略的创建问题场景当策略需要复杂初始化时直接在客户端创建会导致代码耦合。解决方案使用工厂模式封装创建逻辑依赖注入如Spring的Bean配置原型模式需要时克隆已有策略// 基于工厂的解决方案 public class StrategyFactory { private final Config config; public StrategyFactory(Config config) { this.config config; } public DiscountStrategy create(String type) { switch(type) { case VIP: return new VipDiscount(config.getVipDiscountRate()); case SEASONAL: return new SeasonalDiscount(config.getSeasonalRules()); default: throw new IllegalArgumentException(未知策略类型); } } }7.2 如何处理策略间的共享数据问题场景多个策略需要访问相同数据但又不希望策略间直接耦合。解决方案将共享数据放入上下文对象使用ThreadLocal保存线程级共享数据设计无状态策略外部数据源public class PricingContext { private final Product product; private final User user; private final MapString, Object attributes new HashMap(); // getters/setters } public interface PricingStrategy { BigDecimal calculate(PricingContext context); }7.3 如何实现策略的动态替换问题场景需要在运行时根据条件切换策略而不重启应用。解决方案结合配置中心如Nacos、Apollo使用热部署技术如JRebel设计支持动态注册的策略管理器public class DynamicStrategyManager { private final MapString, DiscountStrategy strategies new ConcurrentHashMap(); public void register(String type, DiscountStrategy strategy) { strategies.put(type, strategy); } public void unregister(String type) { strategies.remove(type); } public DiscountStrategy get(String type) { return strategies.get(type); } }7.4 如何避免策略类爆炸问题场景当业务复杂时策略类数量可能急剧增长。解决方案使用策略层次结构继承体系组合模式构建复合策略按业务域划分策略包// 策略层次结构示例 public abstract class BaseDiscount implements DiscountStrategy { protected double baseRate; public BaseDiscount(double baseRate) { this.baseRate baseRate; } } public class TieredDiscount extends BaseDiscount { private final MapDouble, Double tierRates; public TieredDiscount(double baseRate, MapDouble, Double tierRates) { super(baseRate); this.tierRates tierRates; } Override public double applyDiscount(double price) { // 实现分层折扣逻辑 } }8. 策略模式的最佳实践与反模式8.1 十大最佳实践接口设计原则策略接口应该小而专注单一职责方法签名要面向业务而非实现考虑添加策略标识方法如getType()上下文设计技巧提供默认策略支持策略链式调用添加策略执行前后的钩子方法性能优化建议无状态策略使用单例频繁创建的策略考虑对象池策略选择使用枚举而非字符串测试指导方针为每个策略编写独立测试用例测试上下文类的策略切换逻辑模拟策略执行失败场景文档规范为每个策略添加使用场景说明记录策略间的互斥关系注明线程安全性要求与其它模式的协作工厂模式管理策略创建模板方法模式提取公共逻辑装饰器模式增强策略功能异常处理策略定义策略专属异常类型上下文处理策略执行异常添加策略降级机制日志记录建议记录策略切换事件跟踪策略执行耗时标记策略执行失败监控指标设计策略调用次数策略执行耗时策略失败率演进路线规划预留策略版本字段设计策略兼容方案制定策略废弃流程8.2 五大常见反模式上帝策略症状单个策略类实现过多不相关功能解决按单一职责原则拆分策略策略贫血症症状策略接口过于简单导致上下文逻辑膨胀解决将相关行为移入策略接口策略耦合症状策略之间直接互相调用解决通过上下文共享数据或使用中介者模式策略泛滥症状为每个微小变化创建新策略解决使用策略参数化或配置化空策略综合症症状大量策略类只做简单条件转发解决合并简单策略或改用规则引擎9. 策略模式面试深度解析9.1 高频面试题精讲问题1策略模式和工厂模式有什么区别深度解析目的不同工厂关注对象创建策略关注行为封装使用时机工厂在实例化时决定策略在运行时决定关系常组合使用工厂创建策略代码表现工厂方法通常返回具体对象策略方法执行算法问题2什么情况下不应该使用策略模式避坑指南当只有一两种固定算法时过度设计算法非常简单if-else足够策略需要访问大量上下文私有状态破坏封装性能敏感场景虚方法调用开销算法很少变化维护成本高于收益问题3如何测试策略模式实现测试方案单元测试每个具体策略测试上下文类的策略切换模拟策略执行异常性能测试策略选择机制集成测试多策略组合// 示例测试代码 Test public void testVipStrategy() { DiscountStrategy strategy new VipDiscount(); assertEquals(90, strategy.applyDiscount(100), 0.001); } Test public void testContextStrategySwitch() { DiscountContext context new DiscountContext(); context.setStrategy(new VipDiscount()); assertEquals(90, context.executeStrategy(100), 0.001); context.setStrategy(new NewUserDiscount()); assertEquals(80, context.executeStrategy(100), 0.001); }9.2 设计模式组合实战场景电商平台优惠系统需要支持多种优惠策略满减、折扣、赠品策略优先级配置策略冲突检测策略效果分析解决方案设计策略模式实现基础优惠策略责任链模式处理策略优先级组合模式支持策略包观察者模式记录策略应用// 组合模式示例 public class CompositePromotion implements PromotionStrategy { private final ListPromotionStrategy strategies; public CompositePromotion(ListPromotionStrategy strategies) { this.strategies strategies; } Override public PromotionResult apply(Order order) { PromotionResult result new PromotionResult(); for(PromotionStrategy strategy : strategies) { result.combine(strategy.apply(order)); } return result; } } // 责任链模式示例 public abstract class PromotionHandler { private PromotionHandler next; public void setNext(PromotionHandler next) { this.next next; } public PromotionResult handle(Order order) { PromotionResult result applyPromotion(order); if(next ! null) { result.combine(next.handle(order)); } return result; } protected abstract PromotionResult applyPromotion(Order order); }9.3 架构师级思考题问题如何设计支持百万级QPS的策略服务高性能设计方案策略无状态化设计策略预编译如使用Java注解处理器策略缓存热点路径异步策略执行基于RingBuffer的无锁调度// 高性能策略执行器示例 public class StrategyExecutor { private final DisruptorStrategyEvent disruptor; public StrategyExecutor() { this.disruptor new Disruptor( StrategyEvent::new, 1024, DaemonThreadFactory.INSTANCE ); disruptor.handleEventsWith(this::applyStrategy); disruptor.start(); } public CompletableFutureResult execute(Strategy strategy, Input input) { CompletableFutureResult future new CompletableFuture(); disruptor.publishEvent((event, seq) - { event.setStrategy(strategy); event.setInput(input); event.setFuture(future); }); return future; } private void applyStrategy(StrategyEvent event, long seq, boolean endOfBatch) { try { Result result event.getStrategy().execute(event.getInput()); event.getFuture().complete(result); } catch (Exception e) { event.getFuture().completeExceptionally(e); } } }10. 从策略模式到领域设计10.1 策略模式与DDD的融合在领域驱动设计中策略模式可以优雅地实现领域服务// 领域模型中的策略应用 public class Order { private ListOrderLine lines; private PricingStrategy pricingStrategy; public void applyPricingStrategy(PricingStrategy strategy) { this.pricingStrategy strategy; } public BigDecimal calculateTotal() { BigDecimal total lines.stream() .map(line - pricingStrategy.calculatePrice(line)) .reduce(BigDecimal.ZERO, BigDecimal::add); return applyDiscounts(total); } }10.2 策略模式与Clean Architecture在整洁架构中策略模式常出现在Use Case层// 用例层的策略应用 public class PlaceOrderUseCase { private final PaymentStrategyProvider strategyProvider; public PaymentResult placeOrder(Order order, PaymentMethod method) { PaymentStrategy strategy strategyProvider.get(method); return strategy.process(order.getTotal()); } } // 接口定义在领域层 public interface PaymentStrategy { PaymentResult process(BigDecimal amount); }10.3 策略模式与微服务设计在微服务架构中策略模式可以用于服务路由策略public interface ServiceRouter { ServiceInstance select(ListServiceInstance instances); } // 实现类随机路由、轮询路由、权重路由等容错策略public interface FaultToleranceStrategy { T T execute(SupplierT supplier); } // 实现类重试策略、熔断策略、降级策略等消息处理策略public interface MessageHandler { boolean canHandle(Message message); void handle(Message message); } // 不同消息类型对应不同处理策略11. 策略模式的现代演进11.1 函数式编程下的策略模式Java 8中可以用函数接口简化策略模式public class FunctionalStrategy { private final MapString, FunctionDouble, Double strategies Map.of( VIP, price - price * 0.8, NEW, price - price * 0.9 ); public double apply(String type, double price) { FunctionDouble, Double strategy strategies.get(type); if(strategy null) { throw new IllegalArgumentException(未知策略类型); } return strategy.apply(price); } }11.2 策略模式与Lambda表达式Lambda让策略实现更简洁public class LambdaStrategy { public static void main(String[] args) { DiscountStrategy vip price - price * 0.8; DiscountStrategy regular price - price * 0.9; System.out.println(VIP价格: vip.applyDiscount(100)); } } FunctionalInterface interface DiscountStrategy { double applyDiscount(double price); }11.3 策略模式与Stream API结合使用Stream处理策略集合public class StreamStrategy { public static void main(String[] args) { ListDiscountStrategy strategies List.of( price - price * 0.9, price - price 100 ? price - 10 : price ); double finalPrice strategies.stream() .reduce(100.0, (price, strategy) - strategy.applyDiscount(price), (a, b) - b); System.out.println(最终价格: finalPrice); } }12. 策略模式工具与框架支持12.1 Spring中的策略实现方案基于Bean注入的方案// 定义策略接口 public interface DataExportStrategy { String getType(); void export(Data data); } // 实现策略 Service public class CsvExportStrategy implements DataExportStrategy { Override public String getType() { return CSV; } Override public void export(Data data) { /* CSV导出实现 */ } } Service public class ExcelExportStrategy implements DataExportStrategy { Override public String getType() { return EXCEL; } Override public void export(Data data) { /* Excel导出实现 */ } } // 策略路由器 Service public class ExportRouter { private final MapString, DataExportStrategy strategies; Autowired public ExportRouter(ListDataExportStrategy strategyList) { this.strategies strategyList.stream() .collect(Collectors.toMap( DataExportStrategy::getType, Function.identity() )); } public void export(String type, Data data) { DataExportStrategy strategy strategies.get(type); if(strategy null) { throw new IllegalArgumentException(不支持的导出类型); } strategy.export(data); } }基于Spring Boot自动配置的方案// 自动配置类 Configuration public class StrategyAutoConfiguration { Bean ConditionalOnMissingBean public StrategyRegistry strategyRegistry(ListMyStrategy strategies) { return new StrategyRegistry(strategies); } } // 策略接口 public interface MyStrategy { String getType(); void execute(); } // 策略注册中心 public class StrategyRegistry { private final MapString, MyStrategy strategies; public StrategyRegistry(ListMyStrategy strategies) { this.strategies strategies.stream() .collect(Collectors.toMap( MyStrategy::getType, Function.identity() )); } public MyStrategy getStrategy(String type) { return strategies.get(type); } }12.2 策略模式在JUnit中的妙用使用策略模式实现参数化测试public class PricingTest { private final PricingStrategy strategy; public PricingTest(PricingStrategy strategy) { this.strategy strategy; } ParameterizedTest MethodSource(strategyProvider) void testPricing(PricingStrategy strategy) { double result strategy.calculate(100); assertTrue(result 0); } static StreamArguments strategyProvider() { return Stream.of( Arguments.of(new VipPricing()), Arguments.of(new RegularPricing()) ); } }12.3 策略模式与Lombok的结合使用Lombok简化策略实现FunctionalInterface public interface ValidationStrategy { boolean validate(String input); RequiredArgsConstructor public static class LengthStrategy implements ValidationStrategy { private final int min; private final int max; Override public boolean validate(String input) { return input ! null input.length() min input.length() max; } } } // 使用示例 ValidationStrategy strategy new ValidationStrategy.LengthStrategy(3, 10); boolean valid strategy.validate(hello);13. 策略模式代码重构实战13.1 重构前传统if-else实现public class DiscountCalculator { public double calculate(String type, double price) { if(VIP.equals(type)) { return price * 0.8; } else if(NEW.equals(type)) { return price * 0.9; } else if(FESTIVAL.equals(type)) { return price 100 ? price - 20 : price; } else { throw new IllegalArgumentException(未知折扣类型); } } }存在的问题违反开闭原则修改需要改动原有代码方法职责过重包含所有折扣逻辑难以单元测试各种分支耦合在一起业务逻辑不清晰折扣规则混在条件判断中13.2 重构步骤详解第一步提取策略接口public interface DiscountStrategy { String getType(); double apply(double originalPrice); }第二步实现具体策略类public class VipDiscount implements DiscountStrategy { Override public String getType() { return VIP; } Override public double apply(double price) { return price * 0.8; } } public class FestivalDiscount implements DiscountStrategy { Override public String getType() { return FESTIVAL; } Override public double apply(double price) { return price 100 ? price - 20 : price; } }第三步创建策略上下文public class DiscountContext { private final MapString, DiscountStrategy strategies; public DiscountContext(ListDiscountStrategy strategyList) { this.strategies strategyList.stream() .collect(Collectors.toMap( DiscountStrategy::getType, Function.identity() )); } public double calculate(String type, double price) { DiscountStrategy strategy strategies.get(type); if(strategy null) { throw new IllegalArgumentException(未知折扣类型); } return strategy.apply(price); } }第四步客户端使用public class Client { public static void main(String[] args) { ListDiscountStrategy strategies List.of( new VipDiscount(), new FestivalDiscount() ); DiscountContext context new DiscountContext(strategies); double vipPrice context.calculate(VIP, 100); System.out.println(VIP价格: vipPrice); } }13.3 重构效果评估可维护性提升新增折扣类型只需添加新策略类修改现有折扣逻辑不影响其他代码每个策略类职责单一可测试性增强每个策略可以独立测试上下文逻辑可以mock策略测试测试用例更聚焦业务清晰度提高