一文整合工厂模式、模板模式、策略模式

为什么使用设计模式

今天终于有时间系统的整理一下这几个设计模式了, 这几个真是最常用的,用好了它们,你就在也不用一大堆的if else 了。能更好的处理大量的代码冗余问题。

在我们的实际开发中,肯定会有这样的场景:我们的某个方法被多次重复调用,但是每次呢,还需要稍微的改动里面一部分的内容。但是我们常常的写法就是,既然能复用,那我就把原来的接口copy出来一份再改一该里面的内容。(哦,nice,真快,三下五除二解决)但是这样的代码其实就真的只是能运行,给后期运维会带来很大的压力。

倘若我们系统第一版本就这么开发完成了,到第二版需求迭代时。
老板说:“把某某某功能改一下,原来的逻辑统一变了,这个就小改动应该很快吧,给你半天时间。”
然后你说:“我靠,那这工作量太大了, 我每个接口都有这个代码,这一变动,就要全部修改,我点需要两天时间。”
老板说:“这么个破修改你要两天,别再这摸鱼了啊,半天肯定能完事,我自己都能改完, 半天改不完,baibai”
然后你默默翻到我的文章,周末两天连续加班,修改了所有代码,全用上了这套设计模式,以后老板给你估算半天修改时间, 你抢答说:“不用,一两个小时吧就够了”。哈哈哈

设计模式介绍

工厂模式(Factory Pattern)是一种创建型设计模式,用于创建对象的实例化逻辑与客户端代码的分离。在工厂模式中,通过工厂类封装实例化对象的过程,客户端代码不需要直接调用构造函数来实例化对象,而是通过工厂类来创建对象。这样可以提供更灵活性和可维护性,且符合开闭原则。工厂模式常见的几种形式包括简单工厂模式、工厂方法模式和抽象工厂模式。

模板模式(Template Pattern)是一种行为设计模式,用于定义算法的骨架,将可变部分延迟到子类中实现。在模板模式中,定义一个模板方法用于规定算法的流程,同时定义一些抽象方法或钩子方法,子类可以重写这些方法以定义具体实现。通过模板模式,可以避免重复的代码,并提供一个统一的算法框架。

策略模式(Strategy Pattern)是一种行为设计模式,用于定义一系列算法,并将每个算法封装成一个独立的策略对象,客户端可以根据需要在运行时选择算法。在策略模式中,算法之间可以互相替换,独立于客户端,并相互独立运行。策略模式可以提高代码的灵活性和复用性,同时符合开闭原则。

实战代码讲解

常规写法

我们就拿最简单最热门的业务,电商项目的支付功能来讲解。
首先我们创建一个支付的接口。

public interface WxPayService {void pay(PayParams payParams);
}public interface AliPayService {void pay(PayParams payParams);
}

随便定义一下这个接口参数

@Data
public class PayParams {private String name;
}

然后像我们正常的Javaweb项目一样,创建正常的MVC三层结构。

public class WxPayServiceImpl implements PayService{// 实现接口中的方法@Overridepublic void pay(PayParams payParams) {// TODO 第一步:检验一些数据参数是否合格// TODO 第二步:微信支付具体步骤// TODO 第三步:支付成功,进行一些回写、赋值、返回等等操作。}
}public class AliPayServiceImpl implements PayService{// 实现接口中的方法@Overridepublic void pay(PayParams payParams) {// TODO 第一步:检验一些数据参数是否合格// TODO 第二步:支付宝支付具体步骤// TODO 第三步:支付成功,进行一些回写、赋值、返回等等操作。}
}

最后再定义一个controller层,调用

@Autowired
private WxPayService wxPayService;@Autowired
private AliPayService aliPayService;@PostMapping(value = "/WxPay")
public ResponseResult pay(@RequestBody PayParams params) {wxPayService.pay(params);return ResponseResult.success();
}@PostMapping(value = "/AliPay")
public ResponseResult pay(@RequestBody PayParams params) {aliPayService.pay(params);return ResponseResult.success();
}

这样是实现了我们的支付功能,一个微信支付,一个支付宝支付。但是我们会发现,这样写出来的代码,冗余非常多。

接下来我把这个业务代码修改为使用设计模式的格式。

设计模式后的代码

首先我们还是创建一个支付接口。

public interface PayService {void pay(PayParams payParams);
}

然后我们来,实现这个接口,因为我们目前就有两种支付方式,等项目后续升级肯定还会接入越来越多的支付方式,所以我们这里目前就要有两个实现类来实现这个接口, 以后可能更多。

image.png
观看上图我们有发现,在实际的业务逻辑中,其实每个支付的代码中的第一步和第三步都是一样的,所以我们可以把它抽离成一个模板。模板模式这就被使用了。代码如下:

public abstract class PayServiceAbstract implements PayService{// 实现接口中的方法@Overridepublic void pay(PayParams payParams) {before(payParams);realPay(payParams);after(payParams);}// 把这个核心支付功能定义为抽象的方法,留给具体的策略实现类去实现。public abstract void realPay(PayParams payParams);// 支付之前、之后的操作在抽象类中就定义一个模板方法,// 只要掉用了这个抽象方法就自己有该模板可使用。public void before(PayParams payParams){System.out.println("支付前操作");}public void after(PayParams payParams){System.out.println("支付后操作");}
}

上面代码中,我们是用一个抽象类实现了接口,但是抽象还不是具体的实现,它只是固定了一个模板,接下来我们就要有每个支付方式自己的类去做具体的实现,这个也就是策略模式。对一个接口分别使用不同的策略来做不同的事。

支付宝支付的具体策略服务

@Service
public class AliPayServiceAbstractImpl extends PayServiceAbstract{@Overridepublic void realPay(PayParams payParams) {System.out.println("支付宝支付处理中。。。。");}
}

微信支付的具体策略服务

@Service
public class WxPayServiceAbstractImpl extends PayServiceAbstract{@Overridepublic void realPay(PayParams payParams) {System.out.println("微信支付处理中。。。。");}
}

ok,到目前,策略模式 + 模板模式就使用成功了,每当需求再叠加时,我们只需要再加一个具体的策略服务就ok了。别的地方都不需要动。

接下来时控制层的调用。我们如果还是用原来的controller,定义一个微信支付接口一个支付宝支付接口,那也太麻烦了。而且如果以后再有个银行卡支付,apple支付,那每次还要新增接口,真麻烦。所以我们不妨使用工厂模式来解决这个问题,让工厂来帮我们确定到底要用哪种支付。这样就来到了我们的工厂模式。

定义一个工厂

@Service
public class PayFactory {// payType 哪个具体策略服务public PayServiceAbstract getFactory(String payType){try {Class<?> aClass = Class.forName("com.bihe.controller."+payType);PayServiceAbstract payServiceAbstract = (PayServiceAbstract) aClass.getDeclaredConstructor().newInstance();return payServiceAbstract;} catch (Exception e) {throw new RuntimeException(e);}}
}

上面的代码中,我们是用了Java反射,根据我们传递进来的类名,自动反射创建出具体的策略对象。

最后就是我们的控制层了。

@PostMapping(value = "/pay")public ResponseResult pay(@RequestBody PayParams params) {PayServiceAbstract payServiceAbstract = payFactory.getFactory(params.getName());payServiceAbstract.pay(params);return ResponseResult.success();}

这就非常简单了, 我们永远只用这一样接口,前端也不需要判断我什么时候调用weixin支付,什么时候调用ali支付…
前端可以一直调用这个一个接口就可以了,只是把响应支付的关键参数传递过来就可以了。

前端调用
image.png

image.png

🆗啦,这样的代码是不是非常的规整,我们后续如果再添加一个新的支付接口就只需要再加一个具体的策略实现类就可以了,如果老板还要修改以前的统一的业务逻辑,那我们也是只需要在模板中也就是抽象类那层修改就可以啦。

哇,代码终于干净了,整个人都舒服了。哈哈😊

查看原文章可进入我的个人博客: 沉思随笔 。欢迎大家🤞

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

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

相关文章

2024年云仓酒庄新动态:铸就新篇章

原标题&#xff1a;刘总出席成都糖酒会&#xff1a;信任铸就云仓酒庄新篇章&#xff0c;共襄盛举展未来近日&#xff0c;备受瞩目的成都糖酒会盛大开幕&#xff0c;吸引了来自全国各地的业界精英和代表。在这场盛大的行业盛会上&#xff0c;云仓酒庄的刘总亲临现场。 现场&…

以XX大学校园为例的智慧能源管理系统建设方案【能源物联网+智能微电网数字校园、节能校园、低碳校园】

建设背景 贯彻落实《中共中央 国务院关于完整准确全面贯彻新发展理念做好碳达峰碳中和工作的意见》和《国务院关于印发2030年前碳达峰行动方案的通知》要求&#xff0c;把绿色低碳发展纳入国民教育体系。 2021年3月26日为推动信息技术与教育教学深度融合&#xff0c;教育部印…

2.6 IDE(集成开发环境)是什么

IDE&#xff08;集成开发环境&#xff09;是什么 IDE 是 Integrated Development Environment 的缩写&#xff0c;中文称为集成开发环境&#xff0c;用来表示辅助程序员开发的应用软件&#xff0c;是它们的一个总称。 通过前面章节的学习我们知道&#xff0c;运行 C 语言&…

eclipse导入svn项目

1、配置maven 2、用svn引入项目 3一直点击next,到最后选完成。

基于springboot的房屋租赁管理系统+数据库+免费远程调试

项目介绍: 基于springboot的房屋租赁管理系统。Javaee项目&#xff0c;springboot项目&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringBoot JspMaven来实现。MyS…

Qt_day4:2024/3/25

作业1&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和…

【iOS ARKit】播放3D音频

3D音频 在前面系列中&#xff0c;我们了解如何定位追踪用户&#xff08;实际是定位用户的移动设备&#xff09;的位置与方向&#xff0c;然后通过摄像机的投影矩阵将虚拟物体投影到用户移动设备屏幕。如果用户移动了&#xff0c;则通过VIO 和 IMU更新用户的位置与方向信息&…

钡铼技术R40路由器助力构建无人值守的智能化污水处理厂

钡铼技术R40路由器作为智能化污水处理厂的关键网络设备&#xff0c;发挥着至关重要的作用&#xff0c;助力构建无人值守的智能化污水处理系统。在现代社会&#xff0c;污水处理是城市环境保护和可持续发展的重要组成部分&#xff0c;而智能化污水处理厂借助先进的技术和设备&am…

后端常问面经之Java基础

基本数据类型 Java中有8种基本数据类型&#xff1a; 6种数字类型&#xff1a; 4种整数型&#xff1a;byte、short、int、long 2种浮点型&#xff1a;float、double 1种字符类型&#xff1a;char 1种布尔类型&#xff1a;boolean 数据类型的默认值以及所占空间如下&#x…

由浅到深认识Java语言(25):正则表达式

该文章Github地址&#xff1a;https://github.com/AntonyCheng/java-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.c…

2024 Python3.10 系统入门+进阶(三):Python变量类型和运算符

目录 一、Python变量的定义和使用二、Python整数类型&#xff08;int&#xff09;详解三、Python小数/浮点数&#xff08;float&#xff09;类型详解四、Python复数类型(complex)详解---了解五、Python字符串详解(包含长字符串和原始字符串)5.1 处理字符串中的引号5.2 字符串的…

后端常见面经之JVM

JVM组成 有垃圾回收的是哪些地方&#xff1f; 垃圾回收主要是针对堆内存中的对象进行的&#xff0c;包括以下几个方面&#xff1a; 堆内存&#xff1a;垃圾回收主要针对堆内存中不再被引用的对象进行回收&#xff0c;包括新生代和老年代中的对象。 永久代/元空间&#xff1a…

Selenium 自动化 —— 切换浏览器窗口

更多内容请关注我的 Selenium 自动化 专栏&#xff1a; 入门和 Hello World 实例使用WebDriverManager自动下载驱动Selenium IDE录制、回放、导出Java源码浏览器窗口操作 平时我们在使用浏览器时&#xff0c;通常会打开多个窗口&#xff0c;然后再多个窗口中来回切换&#xf…

众邦科技CRMEB商城商业版任意文件写入getshell 0day

代码审计 接口&#xff1a;/adminapi/system/crud 处理的代码如下 public function save(SystemCrudDataService $service, $id 0){$data $this->request->postMore([[pid, 0],//上级菜单id[menuName, ],//菜单名[tableName, ],//表名[modelName, ],//模块名称[table…

手机网页视频无水印采集工具|抖音视频关键词批量下载软件

轻松获取手机网页视频无水印的神器&#xff01;让您随心所欲畅享精彩视频内容&#xff01; 随着网络视频的盛行&#xff0c;如何方便快捷地获取您感兴趣的视频内容成为一大需求。现推出一款手机网页视频无水印采集工具&#xff0c;功能强大&#xff0c;操作简便&#xff0c;助您…

[项目前置]如何用webbench进行压力测试

测试软件 采用webbench进行服务器性能测试。 Webbench是知名的网站压力测试工具&#xff0c;它是由Lionbridge公司开发。 webbench的标准测试可以向我们展示服务器的两项内容&#xff1a; 每秒钟相应请求数 和 每秒钟传输数据量 webbench测试原理是&#xff0c;创建指定数…

03-CSS盒模型(padding、margin、opactiy、cursor、display、css3前缀)

一、CSS盒模型 CSS 盒模型规定了处理元素内容、内边距、边框 和 外边距 的方式。最内部分是元素内容&#xff0c;直接包围内容的是内边距。内边距呈现了元素的背景。内边距的边缘是边框。边框以外是外边距。 1.元素的尺寸: height 设置元素的高度。属性值&#xff1a;auto&am…

开源流程图表库(01):Mermaid.js生成流程图、时序图、甘特图等

一、Mermaid.js的特点 Mermaid.js是一个用于生成流程图、时序图、甘特图等各种图表的开源库。它使用简洁的文本语法来描述图表结构&#xff0c;并将其转换为可视化的图形。 Mermaid.js的主要特点包括&#xff1a; 简洁易用&#xff1a;Mermaid.js使用简单的文本语法来描述图表…

FPGA电平标准

1.LVTTL&#xff1a;&#xff08;3.3v&#xff09; 2.LVCOMS&#xff1a;&#xff08;1.8v&#xff09; 3.LVDS&#xff08;1.8v&#xff09;&#xff1a;LVDS_25&#xff08;2.5v&#xff09; 4&#xff1a;如果是ddr3与fpga相连接fpga的vcco推荐&#xff08;1.5v&#xff09;…

Qt实现简易的多线程TCP服务器(支持多个客户端连接)附源码

目录 一.UI界面的设计 二.服务器的启动 三.实现自定义的TcpServer类 1.在widget中声明自定义TcpServer类的成员变量 2.在TcpServer的构造函数中对于我们声明的m_widget进行初始化&#xff0c;m_widget我们用于后续的显示消息等&#xff0c;说白了就是主界面的更新显示等 …