策略模式随笔~

在这里插入图片描述

若感行文枯燥,请移步至文末Gitee地址中查看源码自行测试感受策略模式之魅力。

一、策略模式的核心概念

策略模式的定义

定义算法族,封装每个算法,使其可互换。

核心三要素

  • Context:上下文,负责接收客户端请求并委托具体策略对象处理,实现业务逻辑与算法实现的解耦。
  • Strategy:定义接口和规范
  • ConcreteStrategy:具体的实现策略

如果把策略模式想象成一个万能遥控器,遥控器通过不同的控制卡控制不同的设备实现不同的功能;遥控器承担Context角色,作为控制中枢提供统一操作入口;控制卡接口插槽则是对应Strategy,定义标准功能;空调、灯光、音箱控制卡则是具体的实现策略(ConcreteStrategy),各自实现温度调节、亮度调控、音量控制等具体功能。

本质

Java中推荐面向接口编程,而非面向实现,策略模式作为这一原则的典型应用,通过抽象策略接口与具体实现解耦,有新的扩展需求时,只需要增加其实现即可,而无需对源代码进行改动,也符合对新增开放,对修改关闭的原则(开闭原则)。基于这种设计思想,在新增设备类型时(如加湿器控制卡),只需扩展新的策略实现而无需修改遥控器本体,即无需修改原代码,只在原代码的基础上新增。

模式结构解析

将策略模式的结构应用于真实且常见的业务场景如支付场景,如在门诊收费页面,用户可以选择支付宝、微信、银联支付,不同的支付方式交互的方式不同,则需要不同的支付实现策略,那么结构参考下图:

在这里插入图片描述

二、解决了什么问题&应用场景

应用场景

在支付实际业务场景中,我们需要使用支持不同的支付方式如:支付宝、微信、银联,每种支付方式调用的接口API、请求参数、返回结果各不相同,有时系统有接入新的支付方式的需求,同时支付相关的业务逻辑比较复杂,每种支付方式的实现代码都会比较长,尤其是聚合了多种支付方式的系统,在维护和开发时成本都更高。

解决了什么问题

策略模式解决了以下痛点:

  1. 代码耦合高:不同支付方式实现混杂在业务逻辑中,存在大量if-else/switch分支
  2. 扩展成本高:新增支付方式需要修改原有支付逻辑,违反开闭原则
  3. 可维护性差:单个方法可能膨胀至上千行,参数传递混乱(如不同支付方式参数通过Map传递)
  4. 测试便利性: 新增策略时可以直接测试新逻辑,不影响原逻辑

代码示例

使用伪代码展示当业务逻辑复杂时,if、switch、策略模式各自的实现方案。

if-else
@Slf4j
@Service
public class IfPaymentServiceImpl implements IfPaymentService {@Overridepublic String pay(String type, BigDecimal amount) {if (Constant.PAYConstant.ALI_PAY.equals(type)) {return "支付宝支付成功,金额:" + amount;} else if (Constant.PAYConstant.WECHAT_PAY.equals(type)) {return "微信支付成功,金额:" + amount;} else if (Constant.PAYConstant.UNION_PAY.equals(type)) {return "银联支付成功,金额:" + amount;}throw new IllegalArgumentException("无效支付方式");}
}
switch-case
public class SwitchPaymentServiceImpl implements SwitchPaymentService {@Overridepublic String pay(String type, BigDecimal amount) {switch (type) {case Constant.PAYConstant.ALI_PAY:return "支付宝支付成功,金额:" + amount;case Constant.PAYConstant.WECHAT_PAY:return "微信支付成功,金额:" + amount;case Constant.PAYConstant.UNION_PAY:return "银联支付成功,金额:" + amount;default:throw new IllegalArgumentException("无效支付方式");}}
}
策略模式

支付方式的策略工厂,类比于使遥控器找到对应的功能的控制卡。

/*** 支付方式的策略工厂*/
@Slf4j
@Component
public class PaymentStrategyFactory {/*** 策略池*/private final Map<String, PaymentService> STRATEGY_MAP = new ConcurrentHashMap<>();@Resourceprivate List<PaymentService> strategies;/*** Spring启动时注入所有的支付策略*/@PostConstructpublic void initStrategies() {for (PaymentService strategy : strategies) {log.info("注入策略:{}", strategy.getClass().getSimpleName());String type = strategy.getClass().getSimpleName().replace("Strategy", "");STRATEGY_MAP.put(type, strategy);}}/*** 根据上下文获取支付策略* @param type 上下文参数* @return 支付策略*/public PaymentService getStrategy(String type) {PaymentService paymentService = STRATEGY_MAP.get(type);return Optional.ofNullable(paymentService).orElseThrow(() -> new IllegalArgumentException("无效支付类型"));}}

类比于遥控器中插槽,定义标准功能。

public interface PaymentService {/*** 支付接口*/String pay(String type, BigDecimal amount);
}

具体实现策略,指定遥控器可以控制设备的具体功能的视线方式。

@Slf4j
@Component
public class AlipayStrategy implements PaymentService {@Overridepublic String pay(String type, BigDecimal amount) {try {Thread.sleep(2000);} catch (Exception e) {log.info("异常", e);}return "支付宝支付成功,金额:" + amount;}
}

代码地址

源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77107.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux的目录结构(介绍,具体目录结构)

目录 介绍 具体目录结构 简洁的目录解释 详细的目录解释 介绍 Linux的文件系统是采用级层式的树状目录结构&#xff0c;在此结构的最上层是根目录“/”。Linux的世界中&#xff0c;一切皆文件&#xff08;比如&#xff1a;Linux会把硬件映射成文件来管理&#xff09; 具体目…

AWS CloudFront加速S3配置跨域

1、点击分配 源我们就选择S3–>选择我们要加速的S3存储桶 2、创建OAC访问方式 在我们的来源访问处–>来源访问控制设置(推荐)–>选择创建新的OAC(Create new OAC)–>自定义名字按默认选项保存–>选择刚刚新创建的OAC 3、选择查看器的配置 根据具体情况&#x…

进程控制(上)【Linux操作系统】

进程控制 写时拷贝 本质是一种减少深拷贝的方法 Linux中有很多拷贝的场景都用得上写时拷贝&#xff0c;下面以创建子进程时的写时拷贝为例&#xff1a; 子进程被创建的时候&#xff1a; 会继承父进程的mm_struct和页表 所以子进程刚刚继承时&#xff0c;父子进程的代码和数据…

Flutter 强制横屏

在 Flutter 中&#xff0c;可以通过设置 SystemChrome 来强制应用横屏显示。以下是实现这一功能的详细步骤和代码示例&#xff1a; 步骤 1&#xff1a;导入必要的包 确保在文件顶部导入了 services.dart 包&#xff0c;因为 SystemChrome 类位于该包中。 import package:flut…

Git完全指南:从入门到精通版本控制 ------- Git核心命令(6)

Git核心命令完全指南&#xff1a;从入门到高效协作 前言 在软件开发领域&#xff0c;Git已成为现代版本控制的代名词。据统计&#xff0c;全球超过90%的开发团队使用Git进行代码管理。然而&#xff0c;许多开发者仅停留在基础命令的机械使用层面&#xff0c;未能真正掌握Git命…

关于Newtonsoft.Json

历史 Newtonsoft.Json&#xff08;也称为 Json.NET&#xff09;是由 James Newton - King 开发的一个开源的 JSON 处理库&#xff0c;它于 2007 年首次发布。在早期&#xff0c;.NET 平台缺乏一个强大且灵活的 JSON 处理工具&#xff0c;Newtonsoft.Json 应运而生&#xff0c;…

git reset详解

一、git reset 的核心作用 用于 移动当前分支的 HEAD 指针 到指定的提交&#xff0c;并可选择是否修改工作区和暂存区。 ⚠️ 注意&#xff1a;若提交已被推送到远程仓库&#xff0c;强制重置&#xff08;--hard&#xff09;后需谨慎操作&#xff0c;避免影响协作。 二、三种模…

【unity游戏开发入门到精通——UGUI】CanvasScaler画布缩放器组件

注意&#xff1a;考虑到UGUI的内容比较多&#xff0c;我将UGUI的内容分开&#xff0c;并全部整合放在【unity游戏开发——UGUI】专栏里&#xff0c;感兴趣的小伙伴可以前往逐一查看学习。 文章目录 一、CanvasScaler画布缩放器组件是什么二、CanvasScaler的三种适配模式1、Cons…

Kubernetes控制平面组件:API Server Webhook 授权机制 详解

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;Kubernetes控…

Python自动化办公

第五篇&#xff1a;Python自动化办公&#xff1a;10行代码搞定重复性工作 适合读者&#xff1a;职场人士、数据分析师 | 阅读时长&#xff1a;12分钟 引言 每天重复处理Excel、PDF或邮件&#xff1f;Python可以帮你自动化这些枯燥任务&#xff0c;节省90%的时间。本文通过实际…

【3】k8s集群管理系列--包应用管理器helm之chart资源打包并推送到harbor镜像仓库

一、chart资源打包 helm package ./web-chart # 当前目录会生成一个tgz的压缩文件二、安装help push插件&#xff08;用于推送前面打包的文件&#xff0c;到镜像仓库&#xff09; .1 下载help-push二进制文件 wget https://github.com/chartmuseum/helm-push/releases/down…

【SpringBoot Druid Mysql多数据源整合】

SpringBoot Druid Mysql多数据源整合 一、背景二、配置结果2.1 SpringBoot java 类配置2.1.1 启动类配置2.1.2 java Config配置 2.2 SpringBoot yml 配置 三、mybatis插件配置3.1 PageHelper的yml配置3.2 mybatis设置自定义字段默认值 四、配置解释 一、背景 公司项目需要连接另…

GGML源码逐行调试(中)

目录 前言1. 简述2. 加载模型超参数3. 加载词汇表4. 初始化计算上下文5. 初始化计算后端6. 创建模型张量7. 分配缓冲区8. 加载模型权重结语下载链接参考 前言 学习 UP 主 比飞鸟贵重的多_HKL 的 GGML源码逐行调试 视频&#xff0c;记录下个人学习笔记&#xff0c;仅供自己参考&…

kubectl的使用

查看集群有多少节点 kubectl get nodes 获取集群状态的摘要信息&#xff08;组件信息&#xff09; kubectl get cs 查看所有命名空间下的所有pod的状态和信息 kubectl get pods --all-namespaces 查看所有命名空间的状态和信息 kubectl get namespaces /ns 查看kube-system…

git在分支上会退到某个指定的commit

1、在idea上先备份好分支&#xff08;基于现有分支new branch&#xff09; 2、在gitlab管理端删除现有分支 3、在idea中大卡terminal&#xff0c;执行 git log 查看commit log ,找到要会退到的commit唯一码&#xff0c;然后执行git reset 唯一码 4、查看本地代码状态 git st…

动态路由, RIP路由协议,RIPv1,RIPv2

动态路由 1、回顾 路由&#xff1a;从源主机到目标主机的过程 源主机发送数据给目标主机&#xff0c;源主机会查看自身的路由信息 如果目标主机是自己同网段&#xff0c;源主机查看的是直连路由 如果目标主机和自己不同网段&#xff0c;源主机查看的是静态路由、动态路由、默…

前端面试-工程化(webpack、vite)

Webpack 相关问题&#xff08;25道&#xff09; Webpack 的核心概念有哪些&#xff1f;&#xff08;Entry、Output、Loader、Plugin、Module、Bundle&#xff09;如何配置 Webpack 的多入口和多出口&#xff1f;Webpack 的 Tree Shaking 实现原理是什么&#xff1f;Loader 和 …

idea 2024 build菜单不见了

Q如题 idea 2024 新版UI添加build和recompile菜单 A如图&#xff0c;右键顶部栏之后&#xff0c;点击Add to Main Toolbar菜单&#xff0c;在里面就能找到Build菜单&#xff0c;添加接口。 Recompile菜单的话在Customize Toolbar中搜索添加才行。

【开源项目】Excel手撕AI算法深入理解(三):时序(RNN、mamba)

项目源码地址&#xff1a;https://github.com/ImagineAILab/ai-by-hand-excel.git 一、RNN 1. RNN 的核心思想 RNN 的设计初衷是处理序列数据&#xff08;如时间序列、文本、语音&#xff09;&#xff0c;其核心特点是&#xff1a; 隐藏状态&#xff08;Hidden State&#xff…

pycharm已有python3.7,如何新增Run Configurations中的Python interpreter为python 3.9

在 PyCharm 中&#xff0c;如果你已经安装了 Python 3.9&#xff0c;并且希望在 Run Configurations 中新增一个 Python 3.9 的解释器&#xff0c;可以按照以下步骤操作&#xff1a; 步骤 1&#xff1a;打开 PyCharm 设置 点击 PyCharm 左上角的 File 菜单。选择 Settings&am…