1.定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
2.模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术,没有关联关系。 因此,在模板方法模式的类结构图中,只有继承关系。
AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。
ConcreteClass : 实现父类所定义的一个或多个抽象方法。
1、聚合支付平台中系统回调代码重构
2、servlet请求的处理
1、解析报文(支付回调验证参数和验证签名)
2、写入系统日志
3、如果解析报文成功,修改支付状态为已经成功并返回不同的支付结果
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.0.1.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.10version>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>2.6version>
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}
1.)优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2.)缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
3.)适用场景
在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。