文档章节

【聚合支付平台】如何智用【模板+工厂】设计模式来实现异步回调

须臾之余
 须臾之余
发布于 05/12 12:05
字数 1505
阅读 522
收藏 24

写在前面:设计模式源于生活,而又高于生活!

异步回调流程

  1. 解析报文(验证签名)
  2. 日志收集(相同)
  3. 如果解析报文成功的话,修改支付状态为已经成功.返回不同的支付结果

模版方法设计模式

提前定义好整体的骨架,不同的行为让子类实现,相同的行为直接定义在抽象类中复用。

相同的行为就定在抽象方案中,不同的行为的实现子类实现

核心设计要点

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/blog/3046848

——【奇思妙想】如何给网关设计一款专属的权限控制【责任链设计模式】   

https://my.oschina.net/u/3995125/blog/3047755

版权@须臾之余https://my.oschina.net/u/3995125

本文参考:蚂蚁课堂:http://www.mayikt.com

© 著作权归作者所有

须臾之余
粉丝 126
博文 69
码字总数 180595
作品 0
吉安
程序员
私信 提问
加载中

评论(3)

秋田君
秋田君
@Async注解 在这种情况能生效吗?
须臾之余
须臾之余 博主
可以
秋田君
秋田君
相同类中调用aop不是会实效吗?
从设计模式角度分析Promise:手撕Promise并不难

前言 Promise作为异步编程的一种解决方案,比传统的回调和事件更加强大,也是学习前端所必须要掌握的。作为一个有追求的前端,不仅要熟练掌握Promise的用法,而且要对其实现原理有一定的理解...

SundialDream1
05/01
0
0
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
java的回调函数,本身算是工厂模式吗?

一直以来都没怎么学习过设计模式 今天在详细了解java的工厂模式时,意外的觉得这货不就是回调函数吗? java的回掉函数,可以用抽象类或是接口实现。而今天从《设计模式之禅》中看的工厂模式,...

优秀良民
2016/05/08
256
2
JavaScript 常见设计模式

前言 设计模式,这一话题一直都是程序员谈论的"高端"话题之一。许多程序员从设计模式中学到了设计软件的灵感和解决方案。 有人认为设计模式只在 C++或者 Java 中有用武之地,JavaScript 这种...

YeeWang王大白
03/08
0
0
每天一个设计模式之订阅-发布模式

博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用(靠这吃饭)和(纯粹喜欢)两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :)...

godbmw
2018/12/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mysql备份还有这么多套路,还不了解下?

逻辑备份和物理备份 逻辑备份 逻辑备份用于备份数据库的结构(CREAET DATABASE、CREATE TABLE)和数据(INSERT),这种备份类型适合数据量小、跨SQL服务器、需要修改数据等场景。如mysqldump...

架构文摘
23分钟前
6
0
吊打面试官——秒杀系统设计

首先设计一个系统之前,我们需要先确认我们的业务场景是怎么样子的,我就带着大家一起假设一个场景好吧。 场景 我们现在要卖100件下面这个婴儿纸尿裤,然后我们根据以往这样秒杀活动的数据经...

java后端开发
28分钟前
5
0
高频电子电路电磁兼容的设计要点

电磁兼容的问题常发生于高频状态下,个别问题(电压跌落与瞬时中断等)除外。高频思维,总而言之,就是器件的特性、电路的特性,在高频情况下和常规中低频 状态下是不一样的,如果仍然按照普...

demyar
30分钟前
5
0
JDK 12 JVM 垃圾回收器 Shenandoah GC 的实践案例

https://www.infoq.cn/article/L4LU1J0VxXtA6ASeGYbV

perofu
39分钟前
4
0
Linux下的计划任务--cron

linux任务计划cron介绍 大部分系统管理工作都是通过定期自动执行某个脚本来完成的,Linux的cron就是用来定期执行脚本的。 Linux任务计划功能的操作都是通过crontab命令来完成的,常用的选项有...

爱米修啊
41分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部