【聚合支付平台】如何智用【模板+工厂】设计模式来实现异步回调
写在前面:设计模式源于生活,而又高于生活!
异步回调流程
- 解析报文(验证签名)
- 日志收集(相同)
- 如果解析报文成功的话,修改支付状态为已经成功.返回不同的支付结果
模版方法设计模式
提前定义好整体的骨架,不同的行为让子类实现,相同的行为直接定义在抽象类中复用。
相同的行为就定在抽象方案中,不同的行为的实现子类实现
核心设计要点
AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。
ConcreteClass : 实现父类所定义的一个或多个抽象方法。
模版方法抽象类
/** * * @description: 使用模版方法重构异步回调代码 */ @Slf4j @Component public abstract class AbstractPayCallbackTemplate { /** * 异步回调业务 */ public String asyncCallBack() { // 1. 支付回调验证参数 Map<String, String> verifySignatureMap = verifySignature(); // 2. 参数验证成功,写入日志中 payLog(verifySignatureMap); String analysisCode = verifySignatureMap.get("analysisCode"); if (!analysisCode.equals(PayConstant.RESULT_PAYCODE_200)) { return resultFail(); } // 3. 执行回调异步相关逻辑 return asyncService(verifySignatureMap); } /** * 使用多线程异步写入日志 */ @Async protected void payLog(Map<String,String> verifySignatureMap){ log.info(">>>>>>>>>>第二步 写入payLog........{}",verifySignatureMap); } /** * 实现业务解析操作 */ protected abstract String asyncService(Map<String,String> verifySignatureMap); /** * 异步返回成功结果 */ protected abstract String resultSuccess(); /** * 异步返回失败结果 */ protected abstract String resultFail(); /** * 支付回调验证参数 */ protected abstract Map<String,String> verifySignature(); }
具体实现模版
①AliPayCallbackTemplate
/** * @title: AliPayCallbackTemplate */ @Component @Slf4j public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate { @Override protected Map<String, String> verifySignature() { //>>>>支付宝回调报文伪代码>>>> log.info(">>>>>第一步 解析支付宝数据报文.....verifySignature()"); Map<String, String> verifySignature = new HashMap<>(); verifySignature.put("price", "10000"); verifySignature.put("orderDes", "充值会员"); // 支付状态为1表示为成功.... verifySignature.put("aliPayMentStatus", "1"); verifySignature.put("aliPayOrderNumber", "20190511"); // 解析报文是否成功 200 为成功.. verifySignature.put("analysisCode", PayConstant.RESULT_PAYCODE_200); return verifySignature; } @Override protected String asyncService(Map<String, String> verifySignatureMap) { log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap); String paymentStatus = verifySignatureMap.get("aliPayMentStatus"); if (paymentStatus.equals("1")) { String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber"); log.info(">>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付..."); } return resultSuccess(); } @Override protected String resultSuccess() { return PayConstant.ALIPAY_RESULT_SUCCESS; } @Override protected String resultFail() { return PayConstant.ALIPAY_RESULT_FAIL; } }
②UnionPayCallbackTemplate
/** * @title: UnionPayCallbackTemplate */ @Component @Slf4j public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate { @Override protected Map<String, String> verifySignature() { //>>>>银联回调报文伪代码>>>>>>>> log.info(">>>>>第一步 解析银联数据报文.....verifySignature()"); Map<String, String> verifySignature = new HashMap<>(); verifySignature.put("price", "10000"); verifySignature.put("orderDes", "充值会员"); // 支付状态为1表示为成功.... verifySignature.put("paymentStatus", "1"); verifySignature.put("orderNumber", "20190511"); // 解析报文是否成功 200 为成功.. verifySignature.put("analysisCode", PayConstant.RESULT_PAYCODE_200); return verifySignature; } @Override protected String asyncService(Map<String, String> verifySignatureMap) { log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap); String paymentStatus = verifySignatureMap.get("paymentStatus"); if (paymentStatus.equals(PayConstant.PAY_STATUS_SUCCESS)) { String orderNumber = verifySignatureMap.get("orderNumber"); log.info(">>>>orderNumber:{orderNumber},已经支付成功 修改订单状态为已经支付..."); } return resultSuccess(); } @Override protected String resultSuccess() { return PayConstant.UNION_RESULT_SUCCESS; } @Override protected String resultFail() { return PayConstant.UNION_RESULT_FAIL; } }
工厂模式获取模版
/** * @title: TemplateFactory */ public class TemplateFactory { public static AbstractPayCallbackTemplate getPayCallbackTemplate(String templateId) { AbstractPayCallbackTemplate payCallbackTemplate = (AbstractPayCallbackTemplate) SpringUtils.getBean(templateId); return payCallbackTemplate; } }
SpringUtils
@Component public class SpringUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } //获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } //通过name获取 Bean. public static Object getBean(String name) { return getApplicationContext().getBean(name); } //通过class获取Bean. public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } //通过name,以及Clazz返回指定的Bean public static <T> T getBean(String name, Class<T> clazz) { return getApplicationContext().getBean(name, clazz); } }
相关依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <dependencies> <!-- sprinboot web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> </dependencies>
Controller层
/** * @title: TemplateController */ @RestController public class TemplateController { @RequestMapping("/asyncCallBack") public String asyncCallBack(String templateId) { AbstractPayCallbackTemplate payCallbackTemplate = TemplateFactory.getPayCallbackTemplate(templateId); return payCallbackTemplate.asyncCallBack(); } }
程序入口
@SpringBootApplication @EnableAsync public class AppTemplate { public static void main(String[] args) { SpringApplication.run(AppTemplate.class); } }
控制台输出结果
>>>>>第一步 解析支付宝据报文.....verifySignature()
>>>>>第二步 写入payLog........{aliPayOrderNumber=20190511, orderDes=充值会员, price=10000, analysisCode=200, aliPayMentStatus=1}
>>>>>第三步asyncService()verifySignatureMap:{aliPayOrderNumber=20190511, orderDes=充值会员, price=10000, analysisCode=200, aliPayMentStatus=1}
>>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付...
>>>>>第一步 解析银联数据报文.....verifySignature()
>>>>>第二步 写入payLog........{orderNumber=20190511, orderDes=充值会员, price=10000, analysisCode=200, paymentStatus=1}
>>>>>第三步asyncService()verifySignatureMap:{orderNumber=20190511, orderDes=充值会员, price=10000, analysisCode=200, paymentStatus=1}
总结
版权@须臾之余https://my.oschina.net/u/3995125
模版设计模式优缺点
1.优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2.缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
3.适用场景
在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。
工厂设计模式优缺点
优点:
1.代码结构简单。
2.获取产品的过程更加简单。
3.满足了开闭原则,即对拓展开放,对修改关闭。
缺点:
拓展较繁琐,要拓展时,需同时改动抽象工厂和工厂实现类。
对比策略模式和责任链设计模式,请关注博客——须臾之余
——经典设计模式之策略模式【如何重构聚合支付平台,对接【支付宝,微信,银联支付】】
——【奇思妙想】如何给网关设计一款专属的权限控制【责任链设计模式】
版权@须臾之余https://my.oschina.net/u/3995125
本文参考:蚂蚁课堂:http://www.mayikt.com

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【AI实战】手把手教你实现文字识别模型(入门篇:验证码识别)
文字识别在现实生活中有着非常重要的应用,主要由文字检测、内容识别两个关键步骤组成,在本博客之前的文章中已介绍了文字检测、内容识别的经典模型原理(见文章:大话文本检测经典模型:CTPN , 大话文本识别经典模型:CRNN),本文主要从实战的角度介绍如何实现文字识别模型。 在之前的文章中,已经介绍过了跟文字识别相关的实战内容:基于MNIST数据集识别手写数字的实战内容(见文章:训练你的第一个AI模型:MNIST手写数字识别模型),这个相对简单。今天再介绍文字识别的另一个经典应用:验证码识别,作为文字识别的实战入门篇。 验证码在手机APP、WEB网站中非常普遍,主要是为了防止恶意登录、刷票、灌水、爬虫等异常行为,也可能是为了缓解系统的后台压力(例如在秒杀、抢票时,强制要求输入验证码)。本文主要介绍文本型验证码的识别,文本型验证码由数字、英文大小写字母,甚至中文随机组成,再进行变形扭曲、加干扰线、加背景噪音等操作,主要是为了防止被光学字符识别(OCR)之类的程序自动识别出图片上的文字而失去效果,如下图: 由于存在着比较强的干扰信息,因此,直接使用OCR进行识别,效果很不理想,而通过AI可很好...
- 下一篇
老生常谈Java虚拟机垃圾回收机制(必看篇)
二、垃圾收集 垃圾收集主要是针对堆和方法区进行。 程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收。 判断一个对象是否可被回收 1. 引用计数算法 给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。 两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致无法对它们进行回收。 正因为循环引用的存在,因此 Java 虚拟机不使用引用计数算法。 public class ReferenceCountingGC { public Object instance = null; public static void main(String[] args) { ReferenceCountingGC objectA = new ReferenceCountingGC(); ReferenceCountingGC objectB = new ReferenceCountingGC(); objectA.instanc...
相关文章
文章评论
共有0条评论来说两句吧...