什么是模版方法
1.定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。
模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
2.模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术,没有关联关系。 因此,在模板方法模式的类结构图中,只有继承关系。
核心设计要点:
AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现
ConcreteClass : 实现实现父类所定义的一个或多个抽象方法。
模版方法应用场景
- 比如聚合支付平台中系统回调代码重构
- Servlet 请求
模版方法抽象类
@Slf4j
public abstract class AbstractPayCallbackTemplate {
/**
* 异步回调业务
* 1.支付回调参数验证
* 2.支付日志写入-异步处理
* 3.修改支付订单为支付成功
* 4.返回服务端为支付成功
*
* @param verifyString
* @return
*/
public String asyncCallBack(String verifyString) {
if (StringUtils.isEmpty(verifyString)) {
/**当回调参数为空直接返回抛出*/
return fail();
}
Map<String, String> verifySignatureMap = verifySignature(verifyString);
payLog(verifySignatureMap);
String analysisCode = verifySignatureMap.getOrDefault("analysisCode", null);
if (StringUtils.isEmpty(analysisCode) || !PaymentConstants.VERIFY_SIGNA_SUCCESS.equals(analysisCode)) {
/**解析码失败直接返回抛出*/
return fail();
}
return asyncService(verifySignatureMap);
}
/**
* 支付回调验签,每个支付回调验签方法不相同,所以让各自子类实现
*
* @param verifyString 回调字符串
* @return
*/
protected abstract Map<String, String> verifySignature(String verifyString);
/**
* 该方法实现对订单状态修改以及支付回调报文拼接并返回
* 每个子类需要实现 实现业务解析操作
*
* @param verifySignatureMap
* @return
*/
protected abstract String asyncService(Map<String, String> verifySignatureMap);
/**
* 支付日志写入,处理成异步,不影响流程
*
* @param stringStringMap
*/
@Async
public void payLog(Map<String, String> stringStringMap) {
log.info("Write Payment Log Parameters:{}", stringStringMap);
}
/**
* 回调失败方法,该方法每个支付方法返回不相同,交给子类实现
* 注意:该返回将会触发支付回调重试机制
*
* @return
*/
protected abstract String fail();
/**
* 回调成功方法,该方法每个支付方法返回不相同,交给子类实现
* 注意:该返回将会触发支付回调重试机制
*
* @return
*/
protected abstract String resultSuccess();
}
|
具体实现模版
@Component
@Slf4j
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected Map<String, String> verifySignature(String verifyString) {
//>>>>假设一下为银联回调报文>>>>>>>>>>>>>>>>
log.info(">>>>>first 解析支付宝据报文.....verifySignature()");
Map<String, String> verifySignature = new HashMap<>(5);
verifySignature.put("price", "1399");
verifySignature.put("orderDes", "会员充值");
// 支付状态为1表示为成功....
verifySignature.put("aliPaymentStatus", "1");
verifySignature.put("aliPayOrderNumber", "201910101011");
// 解析报文是否成功 200 为成功..
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
protected String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
String paymentStatus = verifySignatureMap.get("aliPaymentStatus");
if (PaymentConstants.ALI_PAYMENT_SUCCESS.equals(paymentStatus)) {
String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
log.info(">>>>orderNumber:{},已经支付成功 修改订单状态为已经支付...", aliPayOrderNumber);
} else {
/**相关业务回调失败处理*/
}
return resultSuccess();
}
@Override
protected String resultSuccess() {
return "ok";
}
@Override
protected String fail() {
return "fail";
}
}
|
@Component
@Slf4j
public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected Map<String, String> verifySignature(String verifyString) {
//>>>>假设一下为银联回调报文>>>>>>>>>>>>>>>>
log.info(">>>>>first 解析银联据报文.....verifySignature()");
Map<String, String> verifySignature = new HashMap<>(5);
verifySignature.put("price", "1399");
verifySignature.put("orderDes", "会员充值");
// 支付状态为1表示为成功....
verifySignature.put("unionPaymentStatus", "1");
verifySignature.put("unionPayOrderNumber", "201910101011");
// 解析报文是否成功 200 为成功..
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
protected String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
String paymentStatus = verifySignatureMap.get("unionPaymentStatus");
if (PaymentConstants.ALI_PAYMENT_SUCCESS.equals(paymentStatus)) {
String unionPayOrderNumber = verifySignatureMap.get("unionPayOrderNumber");
log.info(">>>>orderNumber:{},已经支付成功 修改订单状态为已经支付...", unionPayOrderNumber);
} else {
/**相关业务回调失败处理*/
}
return resultSuccess();
}
@Override
protected String resultSuccess() {
return "success";
}
@Override
protected String fail() {
return "fail";
}
}
|
@Component
@Slf4j
public class WeChatPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected Map<String, String> verifySignature(String verifyString) {
//>>>>假设一下为银联回调报文>>>>>>>>>>>>>>>>
log.info(">>>>>first 解析微信据报文.....verifySignature()");
Map<String, String> verifySignature = new HashMap<>(5);
verifySignature.put("price", "1399");
verifySignature.put("orderDes", "会员充值");
// 支付状态为1表示为成功....
verifySignature.put("weChatPaymentStatus", "1");
verifySignature.put("weChatPayOrderNumber", "201910101011");
// 解析报文是否成功 200 为成功..
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
protected String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
String paymentStatus = verifySignatureMap.get("weChatPaymentStatus");
if (PaymentConstants.ALI_PAYMENT_SUCCESS.equals(paymentStatus)) {
String weChatPayOrderNumber = verifySignatureMap.get("weChatPayOrderNumber");
log.info(">>>>orderNumber:{},已经支付成功 修改订单状态为已经支付...", weChatPayOrderNumber);
} else {
/**相关业务回调失败处理*/
}
return resultSuccess();
}
@Override
protected String resultSuccess() {
return "ok";
}
@Override
protected String fail() {
return "fail";
}
}
|
工厂模式获取模版
public class PaymentCallbackFactory {
public static AbstractPayCallbackTemplate getPayCallbackTemplate(String templateId) {
if (StringUtils.isEmpty(templateId)) {
return null;
}
AbstractPayCallbackTemplate payCallbackTemplate = (AbstractPayCallbackTemplate) SpringUtils.getBean(templateId);
return payCallbackTemplate;
}
}
|
模板方法优缺点
1.)优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2.)缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
3.)适用场景
在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。