首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

策略模式:动态切换算法的设计智慧

  • 25-04-24 18:47
  • 2620
  • 10475
juejin.cn

策略模式:动态切换算法的设计智慧

一、模式核心:定义一系列算法并可相互替换

在软件开发中,常常会遇到需要根据不同情况选择不同算法的场景。例如,在电商系统中,根据不同的促销活动(如满减、折扣、赠品)来计算商品的最终价格。

策略模式(Strategy Pattern) 定义了一系列的算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端,核心解决:

  • 算法切换:在运行时根据不同条件动态选择合适的算法。
  • 代码复用:将不同算法封装成独立的策略类,提高代码的复用性。
  • 可维护性:算法的修改和扩展不会影响到使用算法的客户端。

核心思想与 UML 类图

策略模式包含策略接口(Strategy)、具体策略类(Concrete Strategy)和上下文类(Context)。上下文类持有一个策略接口的引用,客户端可以在运行时动态设置上下文类所使用的具体策略。

PlantUML Diagram

二、核心实现:电商促销策略

1. 定义策略接口(促销策略)

java
代码解读
复制代码
public interface PromotionStrategy { double calculatePrice(double originalPrice); // 计算促销后的价格 }

2. 实现具体策略类

满减策略
java
代码解读
复制代码
public class FullReductionStrategy implements PromotionStrategy { private double fullAmount; private double reductionAmount; public FullReductionStrategy(double fullAmount, double reductionAmount) { this.fullAmount = fullAmount; this.reductionAmount = reductionAmount; } @Override public double calculatePrice(double originalPrice) { if (originalPrice >= fullAmount) { return originalPrice - reductionAmount; } return originalPrice; } }
折扣策略
java
代码解读
复制代码
public class DiscountStrategy implements PromotionStrategy { private double discountRate; public DiscountStrategy(double discountRate) { this.discountRate = discountRate; } @Override public double calculatePrice(double originalPrice) { return originalPrice * discountRate; } }
无促销策略
java
代码解读
复制代码
public class NoPromotionStrategy implements PromotionStrategy { @Override public double calculatePrice(double originalPrice) { return originalPrice; } }

3. 实现上下文类(购物车)

java
代码解读
复制代码
public class ShoppingCart { private PromotionStrategy promotionStrategy; public void setPromotionStrategy(PromotionStrategy promotionStrategy) { this.promotionStrategy = promotionStrategy; } public double checkout(double originalPrice) { if (promotionStrategy == null) { promotionStrategy = new NoPromotionStrategy(); } return promotionStrategy.calculatePrice(originalPrice); } }

4. 客户端使用策略模式

java
代码解读
复制代码
public class ClientDemo { public static void main(String[] args) { ShoppingCart cart = new ShoppingCart(); // 无促销活动 cart.setPromotionStrategy(new NoPromotionStrategy()); double price1 = cart.checkout(100); System.out.println("无促销活动,最终价格:" + price1); // 满 100 减 20 cart.setPromotionStrategy(new FullReductionStrategy(100, 20)); double price2 = cart.checkout(120); System.out.println("满 100 减 20,最终价格:" + price2); // 打 8 折 cart.setPromotionStrategy(new DiscountStrategy(0.8)); double price3 = cart.checkout(150); System.out.println("打 8 折,最终价格:" + price3); } }

输出结果:

plaintext
代码解读
复制代码
无促销活动,最终价格:100.0 满 100 减 20,最终价格:100.0 打 8 折,最终价格:120.0

三、进阶:策略模式与工厂模式结合

在实际应用中,为了更方便地管理和获取策略对象,可以将策略模式与工厂模式结合。

java
代码解读
复制代码
public class PromotionStrategyFactory { public static PromotionStrategy getStrategy(String strategyType) { switch (strategyType) { case "full_reduction": return new FullReductionStrategy(100, 20); case "discount": return new DiscountStrategy(0.8); default: return new NoPromotionStrategy(); } } } public class AdvancedClientDemo { public static void main(String[] args) { ShoppingCart cart = new ShoppingCart(); // 使用工厂获取策略 cart.setPromotionStrategy(PromotionStrategyFactory.getStrategy("full_reduction")); double price = cart.checkout(120); System.out.println("使用工厂获取策略,最终价格:" + price); } }

四、框架与源码中的策略模式实践

1. Java 的 Comparator 接口

在 Java 中,Comparator 接口就是策略模式的典型应用。通过实现不同的 Comparator 接口,可以为不同的排序需求提供不同的排序策略。

java
代码解读
复制代码
import java.util.Arrays; import java.util.Comparator; public class ComparatorDemo { public static void main(String[] args) { Integer[] numbers = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}; // 升序排序 Arrays.sort(numbers, Comparator.naturalOrder()); System.out.println("升序排序:" + Arrays.toString(numbers)); // 降序排序 Arrays.sort(numbers, Comparator.reverseOrder()); System.out.println("降序排序:" + Arrays.toString(numbers)); } }

2. Spring 的 ResourceLoader

Spring 框架中的 ResourceLoader 接口及其实现类也是策略模式的应用。不同的 ResourceLoader 实现类可以根据不同的资源类型(如文件、类路径资源、URL 资源等)提供不同的资源加载策略。

java
代码解读
复制代码
import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringResourceLoaderDemo { public static void main(String[] args) { ResourceLoader resourceLoader = new ClassPathXmlApplicationContext(); Resource resource = resourceLoader.getResource("application.properties"); System.out.println("资源是否存在:" + resource.exists()); } }

五、避坑指南:正确使用策略模式的 3 个要点

1. 避免策略类过多

当策略类过多时,会导致类的数量急剧增加,增加系统的复杂度。可以考虑将一些相似的策略类进行合并,或者使用策略枚举来简化策略的管理。

2. 策略的选择逻辑

在使用策略模式时,需要考虑如何选择合适的策略。可以将策略的选择逻辑封装在上下文类中,或者使用工厂模式来管理策略的创建和选择。

3. 策略的可维护性

每个策略类都应该保持独立和单一职责,避免在策略类中添加过多的业务逻辑。同时,要为策略类提供清晰的文档和注释,方便后续的维护和扩展。

六、总结:何时该用策略模式?

适用场景核心特征典型案例
算法的动态切换需要根据不同条件在运行时动态选择算法电商促销、排序算法选择
代码复用和可维护性多个算法具有相似的接口,需要提高代码的复用性和可维护性图形绘制算法、加密算法
避免使用大量条件语句避免在代码中使用大量的 if-else 或 switch 语句游戏中的角色技能、状态机

策略模式通过将算法封装成独立的策略类,实现了算法的动态切换和代码的复用,是一种非常实用的设计模式。下一篇我们将深入探讨模板方法模式,解析如何定义算法骨架并延迟实现细节,敬请期待!

扩展思考:策略模式 vs 状态模式

类型核心思想适用场景
策略模式定义一系列算法并可相互替换,客户端主动选择策略算法的动态切换、代码复用
状态模式对象的行为依赖于其状态,状态的改变会导致行为的改变对象的行为随状态变化、状态机

理解这种差异,能帮助我们在不同场景下选择更合适的设计模式。

注:本文转载自juejin.cn的AronTing的文章"https://juejin.cn/post/7496335321802915866"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top