经典设计模式之模板方法模式【聚合支付平台使用模板+工厂实现异步回调】

1、什么是模板方法设计模式

        1.定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
        2.模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术,没有关联关系。 因此,在模板方法模式的类结构图中,只有继承关系。

2、模板方法模式设计核心要点

AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。
ConcreteClass : 实现父类所定义的一个或多个抽象方法。

3、应用场景

1、聚合支付平台中系统回调代码重构
2、servlet请求的处理

4、异步回调

流程

1、解析报文(支付回调验证参数和验证签名)
2、写入系统日志
3、如果解析报文成功,修改支付状态为已经成功并返回不同的支付结果

maven依赖
<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>
模板方法抽象类
/**
 * @Classname AbstractPayCallbackTemplate
 * @Description 异步回调整体算法骨架
 * @Date 2019/5/16 11:17
 * @Created by mark
 */
@Slf4j
public abstract class AbstractPayCallbackTemplate {
    /**
     * 定义共同行为的骨架
     * @return
     */
    public final String asyncCallBack(){
        //1、验证参数与验证签名
        Map<String,String> verifySignature = verifySignature();
        //2、日志收集
        payLog(verifySignature);
        //3、获取验证签名状态
        String analysisCode = verifySignature.get("analysisCode");
        if(!StringUtils.equals(analysisCode, PayConstant.PAY_RESULT_SUCCESS)){
            return resultFail();
        }
        // 4、更改数据库状态同时返回不同支付结果
        return asyncService(verifySignature);
    }

    /**
     * 支付回调验证参数
     * @return
     */
    protected abstract Map<String, String> verifySignature();

    /**
     * 使用多线程写入日志
     *
     * @param verifySignature
     */
    @Async
    protected void payLog(Map<String, String> verifySignature){
        log.info(">>>第二步 写入数据库....verifySignature:{}", verifySignature);
    }

    /**
     * 返回失败结果
     * @return
     */
    protected abstract String resultFail();

    /**
     * 返回成功结果
     * @return
     */
    protected abstract String resultSuccess();

    /**
     * (业务处理)执行修改订单状态和返回不同的结果给对应的客户
     * @param verifySignature
     * @return
     */
    protected abstract String asyncService(Map<String, String> verifySignature);
}
具体实现类

1、AliPayCallbackTemplate

@Slf4j
@Component
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Override
    protected Map<String, String> verifySignature() {
        //支付宝回调报文伪代码
        log.info(">>>第一步 解析支付宝据报文.....verifySignature()");
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "1000");
        verifySignature.put("orderDes", "充值支付宝会员");
        // 支付状态为1表示为成功....
        verifySignature.put("aliPaymentStatus", PayConstant.PAY_STATUS_SUCCESS);
        verifySignature.put("aliPayOrderNumber", "ali_20190516");
        // 解析报文是否成功 200 为成功..
        verifySignature.put("analysisCode", PayConstant.PAY_RESULT_SUCCESS);
        return verifySignature;
    }

    @Override
    protected String resultFail() {
        return PayConstant.PAY_ALI_FAIL;
    }

    @Override
    protected String asyncService(Map<String, String> verifySignature) {
        log.info(">>>第三步 支付宝支付 asyncService() verifySignatureMap:{}", verifySignature);
        String paymentStatus = verifySignature.get("aliPaymentStatus");
        if (PayConstant.PAY_STATUS_SUCCESS.equals(paymentStatus)) {
            String aliPayOrderNumber = verifySignature.get("aliPayOrderNumber");
            log.info(">>>>orderNumber:{}已经支付成功 修改订单状态为已经支付...",aliPayOrderNumber);
        }
        return resultSuccess();
    }

    @Override
    protected String resultSuccess() {
        return PayConstant.PAY_ALI_SUCCESS;
    }
}

2、UnionPayCallbackTemplate

@Slf4j
@Component
public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Override
    protected Map<String, String> verifySignature() {
        //>>>>银联回调报文伪代码>>>>>>>>
        log.info(">>>>>第一步 解析银联数据报文.....verifySignature()");
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "1000");
        verifySignature.put("orderDes", "充值银联会员");
        // 支付状态为1表示为成功....
        verifySignature.put("unionPaymentStatus", PayConstant.PAY_STATUS_SUCCESS);
        verifySignature.put("unionPayOrderNumber", "union_20190516");
        // 解析报文是否成功 200 为成功..
        verifySignature.put("analysisCode", PayConstant.PAY_RESULT_SUCCESS);
        return verifySignature;
    }

    @Override
    protected String resultFail() {
        return PayConstant.PAY_UNION_FAIL;
    }

    @Override
    protected String resultSuccess() {
        return PayConstant.PAY_UNION_SUCCESS;
    }

    @Override
    protected String asyncService(Map<String, String> verifySignature) {
        log.info(">>>第三步 支付宝支付 asyncService() verifySignatureMap:{}", verifySignature);
        String paymentStatus = verifySignature.get("unionPaymentStatus");
        if (PayConstant.PAY_STATUS_SUCCESS.equals(paymentStatus)) {
            String unionPayOrderNumber = verifySignature.get("unionPayOrderNumber");
            log.info(">>>>orderNumber:{}已经支付成功 修改订单状态为已经支付...",unionPayOrderNumber);
        }
        return resultSuccess();
    }
}
定义常量类

PayConstant

public final class PayConstant {
    /**
     * 支付成功
     */
    public static final String PAY_RESULT_SUCCESS = "200";

    public static final String PAY_STATUS_SUCCESS = "1";

    public static final String PAY_ALI_SUCCESS = "SUCCESS";

    public static final String PAY_ALI_FAIL = "FAIL";

    public static final String PAY_UNION_SUCCESS = "OK";

    public static final String PAY_UNION_FAIL = "ERROR";
}
工厂模式来获取模板
public class TemplateFactory {
    public static AbstractPayCallbackTemplate getPayCallbackTemplate(String templateId){
        return SpringUtils.getBean(templateId,AbstractPayCallbackTemplate.class);
    }
}
工具类
@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);
    }

}
控制台
@RestController
public class TemplateController {
    /**
     * 支付回调
     *
     * @return
     */
    @RequestMapping("/asyncCallBack")
    public String asyncCallBack(String templateId) {
        AbstractPayCallbackTemplate payCallbackTemplate = TemplateFactory.getPayCallbackTemplate(templateId);
        // 使用模版方法模式 执行共同的骨架
        return payCallbackTemplate.asyncCallBack();
    }
}
程序入口
@SpringBootApplication
@EnableAsync
public class TemplateApp {
    public static void main(String[] args) {
        SpringApplication.run(TemplateApp.class,args);
    }
}
输出结果:

访问aliPayCallback地址:http://localhost:8080/asyncCallBack?templateId=aliPayCallbackTemplate

2019-05-20 15:23:14.311  INFO 9892 --- [nio-8080-exec-4] c.x.t.impl.AliPayCallbackTemplate        : >>>第一步 解析支付宝据报文.....verifySignature()
2019-05-20 15:23:14.311  INFO 9892 --- [nio-8080-exec-4] c.x.t.impl.AliPayCallbackTemplate        : >>>第三步 支付宝支付 asyncService() verifySignatureMap:{aliPayOrderNumber=ali_20190516, orderDes=充值支付宝会员, price=1000, aliPaymentStatus=1, analysisCode=200}
2019-05-20 15:23:14.311  INFO 9892 --- [nio-8080-exec-4] c.x.t.impl.AliPayCallbackTemplate        : >>>>orderNumber:ali_20190516已经支付成功 修改订单状态为已经支付...
2019-05-20 15:23:14.311  INFO 9892 --- [cTaskExecutor-2] c.x.t.AbstractPayCallbackTemplate        : >>>第二步 写入数据库....verifySignature:{aliPayOrderNumber=ali_20190516, orderDes=充值支付宝会员, price=1000, aliPaymentStatus=1, analysisCode=200}

访问unionPayCallback地址:http://localhost:8080/asyncCallBack?templateId=unionPayCallbackTemplate

2019-05-20 15:25:24.031  INFO 9892 --- [nio-8080-exec-8] c.x.t.impl.UnionPayCallbackTemplate      : >>>>>第一步 解析银联数据报文.....verifySignature()
2019-05-20 15:25:24.032  INFO 9892 --- [nio-8080-exec-8] c.x.t.impl.UnionPayCallbackTemplate      : >>>第三步 支付宝支付 asyncService() verifySignatureMap:{unionPayOrderNumber=union_20190516, orderDes=充值银联会员, price=1000, unionPaymentStatus=1, analysisCode=200}
2019-05-20 15:25:24.032  INFO 9892 --- [nio-8080-exec-8] c.x.t.impl.UnionPayCallbackTemplate      : >>>>orderNumber:union_20190516已经支付成功 修改订单状态为已经支付...
2019-05-20 15:25:24.032  INFO 9892 --- [cTaskExecutor-3] c.x.t.AbstractPayCallbackTemplate        : >>>第二步 写入数据库....verifySignature:{unionPayOrderNumber=union_20190516, orderDes=充值银联会员, price=1000, unionPaymentStatus=1, analysisCode=200}

5、模板方法设计模式优缺点

1.)优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2.)缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
3.)适用场景
在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值