【西瓜带你学设计模式 | 第十五期 - 策略模式】策略模式 —— 算法封装与动态替换实现、优缺点与适用场景

张开发
2026/6/10 1:08:01 15 分钟阅读
【西瓜带你学设计模式 | 第十五期 - 策略模式】策略模式 —— 算法封装与动态替换实现、优缺点与适用场景
文章目录前言1. 策略模式是什么2. 策略模式解决什么问题3. 核心结构3.1 Strategy抽象策略3.2 ConcreteStrategy具体策略3.3 Context上下文4. 实现思路5. 示例5.1 Strategy抽象策略5.2 ConcreteStrategy具体策略5.2.1 满减策略5.2.2 会员折扣策略5.2.3 阶梯价策略5.3 Context上下文5.4 Client客户端选择策略并调用6. 优缺点6.1 优点6.2 缺点7. 和其他模式怎么区分7.1 策略 vs 简单工厂/工厂方法7.2 策略 vs 模板方法7.3 策略 vs 状态模式8. 适用场景9. 总结前言在很多业务系统里我们经常会遇到“同一类事情不同情况下用不同算法/规则”的需求比如支付方式不同支付宝/微信/银行卡/积分价格计算不同满减、折扣、阶梯价、会员价消息发送不同短信/邮件/推送文件处理不同压缩算法/加密算法/校验算法这些场景通常有一个共同点算法会变但调用方希望保持稳定。策略模式Strategy Pattern要解决的核心就是把算法/规则从使用它的代码中剥离出来让它们以“可替换”的方式独立变化客户端只依赖统一的抽象接口。1. 策略模式是什么策略模式是一种行为型设计模式通过“封装一组可复用的算法”并让它们都实现同一个接口从而做到客户端根据条件选择合适的策略后续新增/修改策略时不需要改动客户端的大结构遵循开闭原则2. 策略模式解决什么问题同一业务流程里会出现多个分支if/else 很多算法或规则经常变化且变化频率高不希望改动调用方逻辑只希望替换不同实现希望代码结构更清晰、可扩展如果代码里出现“根据类型/条件选择不同计算方式”的分支而且会不断增多就很适合策略模式。3. 核心结构3.1 Strategy抽象策略定义策略必须实现的方法例如calculatePrice(...)。3.2 ConcreteStrategy具体策略多个具体类实现同一接口对应不同算法或规则。3.3 Context上下文上下文类持有Strategy负责“在合适时机调用策略”。4. 实现思路按你给的享元模式示例那种“拆角色 实现 示例”的思路策略模式通常是定义Strategy接口统一方法签名写多个ConcreteStrategy不同算法写Context构造时注入策略或运行时切换客户端只跟Context或Strategy交互不关心具体算法细节5. 示例不同规则计算价格5.1 Strategy抽象策略publicinterfacePricingStrategy{doublecalculate(doubleoriginalPrice);}5.2 ConcreteStrategy具体策略5.2.1 满减策略publicclassDiscountByCouponStrategyimplementsPricingStrategy{Overridepublicdoublecalculate(doubleoriginalPrice){// 假设满100减20if(originalPrice100){returnoriginalPrice-20;}returnoriginalPrice;}}5.2.2 会员折扣策略publicclassMemberDiscountStrategyimplementsPricingStrategy{Overridepublicdoublecalculate(doubleoriginalPrice){// 会员9折returnoriginalPrice*0.9;}}5.2.3 阶梯价策略publicclassTieredPricingStrategyimplementsPricingStrategy{Overridepublicdoublecalculate(doubleoriginalPrice){// 假设阶梯200打8折100打9折否则原价if(originalPrice200)returnoriginalPrice*0.8;if(originalPrice100)returnoriginalPrice*0.9;returnoriginalPrice;}}5.3 Context上下文publicclassShoppingCart{privatefinalPricingStrategystrategy;publicShoppingCart(PricingStrategystrategy){this.strategystrategy;}publicdoublecheckout(doubleoriginalPrice){returnstrategy.calculate(originalPrice);}}5.4 Client客户端选择策略并调用publicclassClient{publicstaticvoidmain(String[]args){doubleprice150;ShoppingCartcart1newShoppingCart(newDiscountByCouponStrategy());System.out.println(券后价格: cart1.checkout(price));ShoppingCartcart2newShoppingCart(newMemberDiscountStrategy());System.out.println(会员价: cart2.checkout(price));ShoppingCartcart3newShoppingCart(newTieredPricingStrategy());System.out.println(阶梯价: cart3.checkout(price));}}会发现“选择哪种计算方式”的逻辑被独立出来了策略类ShoppingCart不关心具体算法只负责调用策略将来新增“新计算规则”只要新增一个策略类即可6. 优缺点6.1 优点消除大量 if/else条件分支被策略类替代算法可扩展新增策略不必大改原代码复用性强策略实现可以在多个上下文中使用更符合开闭原则对扩展开放对修改关闭6.2 缺点策略类增多可能导致类数量上升客户端/工厂需要维护“策略选择逻辑”如果选择逻辑仍写一堆 if可能又回来了如果策略之间共享复杂公共逻辑可能需要进一步抽象或结合模板方法/组合等7. 和其他模式怎么区分7.1 策略 vs 简单工厂/工厂方法策略解决“算法/规则如何替换”工厂解决“对象如何创建选择具体策略类”实际项目里经常组合使用工厂负责创建对应策略策略负责算法本体。7.2 策略 vs 模板方法模板方法把“流程骨架”固定把某些步骤延迟到子类实现策略把“某个可变点”直接封装为独立算法运行时可切换7.3 策略 vs 状态模式状态模式对象在不同状态下行为不同且状态通常会在运行过程中自动切换策略模式通常由外部决定当前使用哪种策略策略本身不一定管理“状态流转”8. 适用场景满足以下情况时策略模式很合适系统需要在多种算法/规则之间切换算法实现彼此差异较大但对外暴露统一接口频繁出现“if/else 根据条件选择不同处理”希望将算法从业务流程中解耦便于扩展与测试9. 总结策略模式通过“抽象策略 多个具体策略 上下文持有策略引用”把可变算法/规则从调用方逻辑中解耦出来。客户端只需选择合适的策略即可完成行为替换从而减少分支代码、提高扩展性。

更多文章