Java设计模式 | 基于订单批量支付场景,对策略模式和简单工厂模式进行简单实现
基于订单批量支付场景,对策略模式和简单工厂模式进行简单实现
文章目录
- 策略模式
- 介绍
- 实现
- 抽象策略
- 具体策略
- 1.AliPayStrategy
- 2.WeChatPayStrategy
- 环境
- 使用简单工厂来获取具体策略对象
- 支付方式枚举
- 策略工厂接口
- 策略工厂实现
- 测试使用
- 订单实体类
- 对订单进行批量支付
- 结果
- 扩展一种支付方式:银行卡支付
- 支付策略新增
- 支付枚举新增
- 工厂新增生产银行卡
- 重新测试
策略模式
介绍
以下是菜鸟教程对策略模式的介绍: 策略模式
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
策略模式主要有三个角色:
- 抽象策略(Abstract Strategy):定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。
- 具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,包含了具体的算法实现。
- 环境(Context):维护一个对策略对象的引用,负责将客户端请求委派给具体的策略对象执行。环境类可以通过依赖注入、简单工厂等方式来获取具体策略对象。
实现
抽象策略
我们使用接口来实现抽象策略,规定了支付的公共方法,根据传入的用户名和支付金额进行结算。
package knowledege.designPattern.strategy.test1;import java.math.BigDecimal;public interface PayStrategy {void pay(String name, BigDecimal money);
}
具体策略
初始化微信和支付宝两种支付策略
1.AliPayStrategy
package knowledege.designPattern.strategy.test1;import java.math.BigDecimal;public class AliPayStrategy implements PayStrategy{@Overridepublic void pay(String name, BigDecimal money) {System.out.println("[" +name+ "]使用支付宝支付..." + money + "元");}
}
2.WeChatPayStrategy
package knowledege.designPattern.strategy.test1;import java.math.BigDecimal;public class WeChatPayStrategy implements PayStrategy{@Overridepublic void pay(String name, BigDecimal money) {System.out.println("[" +name+ "]使用微信支付..." + money + "元");}
}
环境
提供设置策略和执行策略的方法
package knowledege.designPattern.strategy.test1;import java.math.BigDecimal;
public class PayContext {private PayStrategy payStrategy;public PayContext(){}public void setPayStrategy(PayStrategy payStrategy){this.payStrategy = payStrategy;}public void executePayStrategy(String name, BigDecimal money){payStrategy.pay(name, money);}
}
使用简单工厂来获取具体策略对象
支付方式枚举
定义枚举并支持静态根据支付方式获取枚举
package knowledege.designPattern.strategy.test1;import lombok.AllArgsConstructor;
import lombok.Getter;@Getter
@AllArgsConstructor
public enum PayWayEnum {PAY_ALI("01","支付宝"),PAY_WE_CHAT("02","微信");public final String payWay;public final String payDesc;public static PayWayEnum getEnumByWay(String payWay){for(PayWayEnum enums: PayWayEnum.values()){if(enums.payWay.equals(payWay)){return enums;}}return null;}
}
策略工厂接口
public interface StrategyFactory {PayStrategy initStrategy();
}
策略工厂实现
package knowledege.designPattern.strategy.test1;import java.util.Objects;public class StrategySimpleFactory {public static PayStrategy initStrategy(String payWay){PayWayEnum payWayEnum = PayWayEnum.getEnumByWay(payWay);if (Objects.isNull(payWayEnum)) {return null;}PayStrategy strategy = null;switch (payWayEnum) {case PAY_ALI:strategy = new AliPayStrategy();break;case PAY_WE_CHAT:strategy = new WeChatPayStrategy();break;}return strategy;}
}
测试使用
订单实体类
package knowledege.designPattern.strategy.test1;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderTestDTO {Integer orderNum;String payPersonName;String payWay;BigDecimal payMoney;
}
对订单进行批量支付
模拟对订单进行批量支付
- 模拟获取一批订单
- 循环订单进行支付
- 根据订单的支付方式,获取支付枚举
- 根据枚举,使用工厂模式获取支付策略
- 根据策略,使用支付环境进行支付
package knowledege.designPattern.strategy.test1;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;public class test1 {public static void main(String[] args) {List<OrderTestDTO> orderList = initOrders();batchPay(orderList);}/*** 获取订单*/public static List<OrderTestDTO> initOrders(){List<OrderTestDTO> orderList = new ArrayList<>();orderList.add(new OrderTestDTO(1,"aaa","01",new BigDecimal("99")));orderList.add(new OrderTestDTO(2,"aaa","02",new BigDecimal("20")));orderList.add(new OrderTestDTO(3,"bbb","01",new BigDecimal("17")));orderList.add(new OrderTestDTO(4,"ccc","02",new BigDecimal("19.88")));return orderList;}/*** 订单批量支付*/public static void batchPay(List<OrderTestDTO> orderList){PayContext payContext = new PayContext();orderList.forEach( order -> {PayStrategy strategy = StrategySimpleFactory.initStrategy(order.getPayWay());payContext.setPayStrategy(strategy);payContext.executePayStrategy(order.getPayPersonName(), order.getPayMoney());});}
}
结果
可以看到每笔订单都成功根据其支付方式支付了。

扩展一种支付方式:银行卡支付
如果需要扩展一种支付方式,才能看出策略+工厂模式的真正优点。
下面我们模拟扩展一种支付方式:银行卡支付
支付策略新增
package knowledege.designPattern.strategy.test1;import java.math.BigDecimal;public class CardStrategy implements PayStrategy{@Overridepublic void pay(String name, BigDecimal money) {System.out.println("[" +name+ "]使用银行卡支付..." + money + "元");}
}
支付枚举新增
PAY_CARD("03","银行卡"),
工厂新增生产银行卡
case PAY_CARD:strategy = new CardStrategy();break;
重新测试

成功适配了银行卡支付,改动较少,又没有更改核心的支付逻辑,符合开闭原则!
相关文章:
Java设计模式 | 基于订单批量支付场景,对策略模式和简单工厂模式进行简单实现
基于订单批量支付场景,对策略模式和简单工厂模式进行简单实现 文章目录 策略模式介绍实现抽象策略具体策略1.AliPayStrategy2.WeChatPayStrategy 环境 使用简单工厂来获取具体策略对象支付方式枚举策略工厂接口策略工厂实现 测试使用订单实体类对订单进行批量支付结…...
【组件专题介绍】什么是组件?
组件定义 卡耐基梅隆大学: 一个不透明的功能实体,能够被第三方组装,且符合一个构件模型。 计算机百科全书: 是软件系统中具有相对独立功能、接口由契约指定、和语境有明显依赖关系、可独立部署、可组装的软件实体。 软件构件…...
Mybatis拦截器
MyBatis插件介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能。 MyBatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用,通过织入拦截器,在不同节点修改一些执行过程中的关键属性&…...
【项目设计】网络对战五子棋(上)
想回家过年… 文章目录 一、项目前置知识1. websocketpp库1.1 http1.0/1.1和websocket协议1.2 websocketpp库接口的前置认识1.3 搭建一个http/websocket服务器 2. jsoncpp库3. mysqlclient库 二、 项目设计1. 项目模块划分2. 实用工具类模块2.1 日志宏封装2.2 mysql_util2.3 j…...
【Overload游戏引擎细节分析】鼠标键盘控制摄像机原理
在上文中分析了摄像机类的实现,在计算投影视图矩阵时需要给摄像机输入其位置及转动四元数。这两个量一般通过鼠标键盘来控制,从而达到控制摄像机的目的。本文分析一下其控制原理。 Overload的摄像机控制实现在类CameraController中,其有三个个…...
VScode运行SVN拉下来的项目
安装依赖包 pnpm install 启动程序 查看package.json文件中的serve,根据这个启动 pnpm dev 在浏览器使用http://localhost:8848/访问...
jmeter集成kafka测试
Kafka的使用 查看kafka的topic ./kafka-topics --bootstrap-server 10.1.9.84:9092 --list 查看topic信息 ./kafka-topics --bootstrap-server 10.1.9.84:9092 --describe --topic topic_example_1 创建topic 创建topic名为test,分区数为8,副本数为…...
Java面试题-UDP\TCP\HTTP
UDP UDP特性 (1)UDP是无连接的:发送数据之前不需要像TCP一样建立连接,也不需要释放连接,所以减少了发送和接收数据的开销 (2)UDP 使用尽最大努力交付:即不保证可靠交付 ࿰…...
使用WPF模仿Windows记事本界面
本次仅模仿Windows记事本的模样,并未实现其功能。 所有代码如下: <Window x:Class"控件的基础使用.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/…...
【目标检测】Co-DETR:ATSS+Faster RCNN+DETR协作的先进检测器(ICCV 2023)
论文:DETRs with Collaborative Hybrid Assignments Training 代码**:https://github.com/Sense-X/Co-DETR 文章目录 摘要一、简介二、本文方法2.1.概述2.2.协同混合分配训练2.3. 定制的正 Query 生成2.4. Co-DETR为何有效1、丰富编码器的监督2、通过减少…...
iOS QQ登录SDK升级后报错Duplicate interface definition for class ‘TencentOAuth‘修复
起因 最近发现QQ登录SDK sdk-Lite3.3.8 TencentOpenAPI 在部分手机上会崩溃到初始化位置_tencentOAuth [[TencentOAuth alloc] initWithAppId:appid andDelegate:self];, 比如:iPhone6p 版本12.5.4,iPhone8p 版本14.1,iPad版本1…...
laravel中锁以及事务的简单使用
一、首先来说一下什么是共享锁?什么是排他锁? 共享:我可以读 写 加锁 , 别人可以 读 加锁。 排他:只有我 才 可以 读 写 加锁 , 也就是说,必须要等我提交事务,其他的才可以操作。 二、简单例子实现加锁 锁…...
Vue+openlayers+projs4实现坐标转换
一、背景 有一堆点数据,需要在地图上标记,只知参考北京54坐标系或西安80坐标系,但具体是哪种不清楚,这时候就需要坐标转换。ps:EPSG:3857(openlayers参照的坐标系) 二、思路 1、研…...
09 创建型模式-建造者模式
1.建造者模式介绍: 建造者模式 (builder pattern), 也被称为生成器模式 , 是一种创建型设计模式 定义: 将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不 同的表示。 2.建造者模式要解决的问题 建造者模式可以将部件和其组装过程分开&am…...
4.9 多协议标记交换MPLS
思维导图: 前言: **4.9 多协议标记交换MPLS笔记** 1. **定义与背景**: - MPLS (多协议标记交换) 是一种由 IETF 开发的新协议。 - “多协议”意味着 MPLS 的上层可以使用多种协议。 - 该协议综合了多家公司的技术,如 C…...
【经历】在职8个月->丰富且珍贵
在职8个月->丰富且珍贵 2021-3~2021-11:面试进入一家做400电话的公司,我进入公司时,加上我只有四个人(老板、人事、业务),开发只有我,所以:产品~设计~前端~后端~测试~上线~维护~培训,只有我自…...
使用GH(命令行)在本地提出Github上的issue、PR,合并PR
使用GH(命令行)在本地提出Github上的issue、PR,合并PR 前言 Github上的一些操作使用Git命令是无法完成的,因此正常流程就是在网页端进行。等一下,你让程序员用网页进行?果然,有命令行工具可以…...
@Scheduled定时器
Scheduled定时器 一、基本使用二、参数说明fixedDelayfixedRateinitialDelaycron 三、cron 表达式参数说明实用性的案例 四、Scheduled注意事项五、配置文件1、fixedDelay2、fixedRate3、cron 一、基本使用 Scheduled // 由Spring定义,用于将方法设置为调度任务。…...
Xshell+screen解决ssh连接 服务器掉线的问题
Linux screen命令解决SSH远程服务器训练代码断开连接后运行中断_linux screen ssh-CSDN博客 Linux命令之screen命令_linux screen_恒悦sunsite的博客-CSDN博客 使用教程: 这里粗略介绍一下 (1)xshell xftp(xshell点这个&#…...
coding_v3
面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台 数组/字符串 1.LC88【合并两个有序数组】 def solve(nums1, m, nums2, n):p1, p2 m-1, n-1tail m n -1while p1 > 0 or p2 > 0:if p1 -1:nums1[tail] nums2[p2]p2…...
SM30表维护视图:实现审计追踪字段的自动化填充
1. SM30表维护视图与审计追踪的完美结合 每次打开企业级SAP系统,看到那些密密麻麻的数据表,我都会想起十年前刚入行时的手忙脚乱。那时候最头疼的就是要手动记录每条数据的修改人和修改时间,不仅效率低下,还经常出错。直到发现了S…...
如何免费突破百度网盘限速:Python直连解析工具终极指南
如何免费突破百度网盘限速:Python直连解析工具终极指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 你是否曾经为百度网盘缓慢的下载速度而烦恼?想要…...
用STM32CubeMX和HAL库驱动RC522 NFC模块,从零实现一个简易门禁(附完整代码)
基于STM32CubeMX与HAL库的RC522门禁系统开发实战 在智能硬件开发领域,NFC技术因其非接触式交互特性,已成为门禁系统的首选方案。本文将完整呈现如何利用STM32CubeMX图形化工具和HAL库,从零构建一个稳定可靠的RC522门禁系统。不同于传统寄存器…...
别再让笔记本在包里‘发烧’了!手把手教你将Windows 11的Modern Standby改回传统S3睡眠
拯救发热的笔记本:Windows 11睡眠模式终极优化指南 你是否经历过这样的场景:合上笔记本放进包里,几小时后取出时发现机身滚烫,电量耗尽,甚至系统卡死需要强制重启?这很可能要归咎于Windows 11默认采用的Mod…...
考研数学二:3个月零基础速成295分,我的极限、积分与微分方程实战笔记(附避坑指南)
考研数学二:3个月零基础速成295分,我的极限、积分与微分方程实战笔记(附避坑指南) 当推免失败的通知突然降临,距离考研仅剩三个月时,我面对着几乎空白的数学二基础。作为计算机专业考生,数学二是…...
用Arduino给LCD1602做个‘表情包’:手把手教你自定义5x7点阵字符(附完整代码)
用Arduino给LCD1602制作个性化表情包:从设计到实现的完整指南 那块1602液晶屏上闪烁的字符是否让你感到审美疲劳?其实只需几行代码,就能让这块经典显示屏焕发新生。想象一下,你的智能花盆能显示笑脸表示湿度正常,哭脸提…...
python terraform-cdk
# 当Python遇见基础设施:聊聊Terraform CDK for Python 最近在云原生和基础设施即代码的圈子里,有个工具逐渐引起了Python开发者的注意——Terraform CDK for Python。如果你熟悉Terraform,但总觉得HCL语言写起来不够顺手,或者你…...
PyTorch GPU环境从下载到验证:避开CUDA、cuDNN版本匹配的坑(2024年最新版)
PyTorch GPU环境从下载到验证:避开CUDA、cuDNN版本匹配的坑(2024年最新版) 当你在终端输入torch.cuda.is_available()却看到False时,那种挫败感我深有体会。去年在部署一个图像分割项目时,我花了整整三天时间排查环境…...
Everspin高性能串口mram芯片MR25H40CDCR
与传统串行EEPROM或闪存不同,串口mram芯片MR25H40CDCR在读写时序上完全兼容这些常见存储器,但有一个关键优势——没有写入延迟。普通串行存储器在两次写入之间需要等待,而Everspin串口mram芯片MR25H40CDCR支持随机访问,读取和写入…...
Jmeter 安装教程:一看就会
随着互联网的不断发展,网站和应用程序的性能测试 变得越来越重要。Apache JMeter 是一款广泛使用的性能测试工具,它强大且使用广泛,适用于各种性能测试需求。不论你是刚刚接触性能测试的新手,还是一位有经验的测试工程师ÿ…...
