当前位置: 首页 > ops >正文

行为设计模式之Strategy(策略)

行为设计模式之Strategy(策略)

摘要:

策略模式是一种行为设计模式,它定义一系列算法并封装为独立对象,使它们可以相互替换。该模式让算法独立于使用它的客户端而变化,适用于需要动态切换算法、避免大量条件语句、实现算法与使用代码分离的场景。文章通过Java代码示例展示了加减乘三种算法的策略实现,并列举了电商定价、游戏AI、金融投资等典型应用领域。策略模式的核心优势在于提高代码扩展性和维护性,符合开闭原则。

1)意图

定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。此模式使得算法可以独立于使用它们的客户而变化。

2)结构

在这里插入图片描述

3)适用性

Strategy 模式适用于:

  • 许多相关的类仅仅是行为有异。
  • 需要使用一个算法的不同变体。
  • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与其算法相关的数据结构。
  • 一个类定义了许多种行为
/*** @author psd 行为设计模式之策略设计模式*/
public class StrategyPattern {public static void main(String[] args) {OperationContext context = new OperationContext(new AddStrategy());context.executeStrategy(1, 2);context = new OperationContext(new SubStrategy());context.executeStrategy(1, 2);context = new OperationContext(new MultiplyStrategy());context.executeStrategy(1, 2);}
}/*** 操作上下文*/
class OperationContext {private Strategy strategy;public OperationContext(Strategy strategy) {this.strategy = strategy;}public void executeStrategy(int a, int b) {strategy.doOperation(a, b);}
}/*** 策略接口*/
interface Strategy {/*** 执行策略* * @param a*            参数a* @param b*            参数b* @return 结果*/public void doOperation(int a, int b);
}class AddStrategy implements Strategy {@Overridepublic void doOperation(int a, int b) {System.out.println("加法:" + (a + b));}
}class SubStrategy implements Strategy {@Overridepublic void doOperation(int a, int b) {System.out.println("减法:" + (a - b));}
}class MultiplyStrategy implements Strategy {@Overridepublic void doOperation(int a, int b) {System.out.println("乘法:" + (a * b));}
}

在这里插入图片描述

1、需要在运行时动态选择算法或行为:

当系统需要在多种算法中选择一种执行,且这个选择可能需要在程序运行时(例如根据用户输入、配置、环境条件)动态决定时。

例子:

排序算法: 一个排序工具类,可能根据数据量的大小、是否已部分有序等因素,在运行时选择使用快速排序、归并排序、插入排序等不同的算法。

导航系统: 导航应用允许用户选择最快路线、最短距离、避开收费、避开高速等不同的路线计算策略。

支付系统: 在结账时,用户可以选择不同的支付策略:支付宝、微信支付、信用卡、PayPal。系统根据用户的选择调用对应的支付处理逻辑。

数据压缩/加密: 根据需求选择不同的压缩算法(ZIP, GZIP, RAR)或加密算法(AES, DES, RSA)。

2、存在多种相似算法或行为,仅具体实现不同:

当完成同一项任务存在多种不同的方式(算法),这些方式在概念上做的是同一件事,但实现细节不同时。

例子:

文件解析: 需要解析不同格式的文件(CSV、JSON、XML),每种格式的解析逻辑不同,但最终目标都是将文件内容转换为内部数据结构。

渲染引擎: 一个图形渲染系统,可能需要支持渲染到不同的目标:屏幕、PDF文件、SVG矢量图。每种目标有不同的渲染实现,但渲染的基本流程(如绘制形状、文本)是相似的。

日志记录: 日志可以输出到不同的目的地:控制台、文件、数据库、网络服务。记录日志的核心行为(记录信息)是相同的,但输出的具体方式不同。

折扣计算: 电商系统中计算商品折扣有多种策略:无折扣、固定折扣、百分比折扣、满减、会员折扣等。它们都是计算最终价格,但计算规则各异。

3、需要避免使用大量的条件语句(if-else / switch-case)来选择算法:

当客户端代码中充斥着大量的条件分支来判断应该使用哪种算法时,代码会变得臃肿、难以阅读和维护。添加新的算法或修改现有算法逻辑都需要修改这些条件分支,违反开闭原则。

策略模式的价值: 它将每个算法封装在独立的策略类中。客户端代码不再直接判断和执行算法,而是持有一个策略接口的引用,并通过这个接口调用算法。算法的选择(即具体策略对象的创建和设置)可以集中管理(如使用工厂模式)或由更高层代码(如用户配置)决定,从而消除了客户端代码中的条件分支。

4、算法的实现细节需要与使用它的代码分离:

当算法的具体实现比较复杂、可能经常变化,或者你希望将算法的实现细节对客户端代码隐藏,以降低耦合度时。

策略模式的价值: 客户端代码只依赖于抽象的Strategy接口,完全不知道具体策略类的内部实现。这使得算法实现的修改、优化甚至替换都不会影响到使用算法的客户端代码。

5、需要方便地扩展新的算法:

当系统预期未来需要支持新的算法变体时。

策略模式的价值: 添加一个新的算法(策略)变得非常简单:只需要实现一个新的策略类,符合Strategy接口即可。无需修改现有的策略类或使用算法的上下文类(Context),完美符合开闭原则。

4)常见应用领域举例:

电商/零售系统:

定价策略(成本加成、竞争定价、促销定价)、折扣策略、运费计算策略(按重量、按体积、固定运费、免邮条件)、库存分配策略(FIFO, LIFO)。

游戏开发:

AI行为策略(不同的敌人有不同的攻击或移动策略)、伤害计算策略(物理伤害、魔法伤害、真实伤害)、资源收集策略。

金融系统:

投资组合管理策略(保守型、平衡型、激进型)、风险评估策略、交易执行策略(市价单、限价单、止损单)。

数据处理/分析系统:

数据清洗策略(处理缺失值、异常值)、特征选择策略、模型选择策略(不同机器学习算法)、数据导出格式策略(CSV, Excel, JSON)。

GUI框架/工具包:

布局管理器策略(FlowLayout, BorderLayout, GridLayout)、组件绘制策略(不同主题/Skin)、事件处理策略(不同平台可能有不同实现)。

工具类库:

Java中的Comparator接口是策略模式的经典应用。你可以为不同的排序需求实现不同的Comparator策略对象。ThreadPoolExecutor的拒绝策略(AbortPolicy, CallerRunsPolicy, DiscardPolicy, DiscardOldestPolicy)也是策略模式的应用。

网络通信:

选择不同的网络传输协议策略(TCP, UDP, HTTP)、数据序列化策略(JSON, Protobuf, XML)、负载均衡策略(轮询、随机、最少连接、响应时间)。

喜欢我的文章记得点个在看,或者点赞,持续更新中ing…

http://www.xdnf.cn/news/14287.html

相关文章:

  • 网络编程(HTTP协议)
  • ShenNiusModularity项目源码学习(34:总结)
  • C/C++数据结构之漫谈
  • React-router、React-router-dom、React-router-native之间的区别
  • 基于深度强化学习的智能机器人路径规划系统:技术与实践
  • Flutter 本地存储全面指南:从基础到高级实践
  • CMake实战:qmake转cmake神器 - pro2cmake.py
  • 【图像处理入门】7. 特征描述子:从LBP到HOG的特征提取之道
  • 智慧金融——解读DeepSeek在银行业务场景的应用【附全文阅读】
  • Kotlin实现文件上传进度监听:RequestBody封装详解
  • Vue 性能优化
  • Flink与Kubernetes集成
  • 数据库相关操作
  • [windows工具]OCR提取文字软件1.1使用教程及注意事项
  • Java—— ArrayList 和 LinkedList 详解
  • 【橘子的AI | 每日一课】Day4!机器学习 (ML) 基础
  • /etc/profile.d/conda.sh: No such file or directory : numeric argument required
  • Nginx-2 详解处理 Http 请求
  • aws(学习笔记第四十四课) opensearch
  • AWS EC2 终极指南:如何选择预装 GPU 驱动和特定功能的最佳 AMI
  • 自然语言处理NLP 学习笔记
  • Jenkins 全面深入学习目录
  • c++ 项目使用 prometheus + grafana 进行实时监控
  • 安卓9.0系统修改定制化____默认开启 开发者选项中的OEM锁解锁选项 开搞篇 五
  • Ubuntu安装Gym及其仿真
  • 基于51单片机的污水ph值和液压监测系统
  • 关于MCU、MPU、SoC、DSP四大类型芯片
  • Python学习小结
  • 山东大学项目实训——基于DeepSeek的智能写作与训练平台(十四)
  • 智能语音交互技术深度解析:从原理到产业实践