什么是模板方法:
(1)定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
(2)模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术,没有关联关系,因此,在模板方法模式的类结构中,只有继承关系。
核心设计要点:
AbstractClass:抽象类,定义并实现一个模板方法,这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应得抽象操作中,推迟到子类去实现。
CoincreteClass:实现父类所定义的一个或多个抽象方法。
我们用模板方法模式实现一个聚合支付:
我们来搭个springBoot项目框架
定义一个支付模板:
/**
* 抽象方法的模本
*/
@Slf4j
public abstract class AbstraractPayCallbackTemplete {
/**
*定义共同行为的骨架
*/
public String asyncCallBack(){
//验证参数和验证签名 每个实现是不一样的
Map<String,String> verifySignature = veriftySigmature();
//日志收集 基本都相同 一般这种日志都存入数据库
payLog(verifySignature);
//获取验证签名状态
String anslySisCode = verifySignature.get("analysisiCode");
//然后进行判断,如果失败
if(!"200".equals(anslySisCode)){
return resultFail();
}
return asyncService(verifySignature);
}
//验证参数和验证签名 每个实现是不一样的
protected abstract Map<String, String> veriftySigmature();
/**
* 写入日志最好采用异步去处理
* @param verifySignature
*/
public void payLog(Map<String, String> verifySignature) {
log.info("写入到数据库=======【{}】"+verifySignature);
}
//更改数据库状态 同时返回不同支付结果
protected abstract String asyncService(Map<String, String> verifySignature);
//返回失败的结果
protected abstract String resultFail();
//返回成功的结果
protected abstract String resultSucces();
}
实现模板:来用伪代码实现小米支付和阿里支付
阿里支付实现:
/**
* 阿里支付实现
*/
@Slf4j
@Component
public class AliPayCallbackTemplete extends AbstraractPayCallbackTemplete {
@Override
protected Map<String, String> veriftySigmature() {
//ali支付伪代码 假设一下为阿里支付pay回调报文>>>>>
log.info(">>>>>>>>>>第一步 解析支付宝报文。。。。。。。。。。veriftySigmature");
Map<String,String> veriftySigmature = new HashMap<>();
veriftySigmature.put("price","899");
veriftySigmature.put("orderDes","商品名称");
//支付状态为1表示成功
veriftySigmature.put("aliPayMentStatus","1");
//支付唯一流水号
veriftySigmature.put("aliOrderNumber","20211111929292");
//解析报文是否成功 假设200是成功
veriftySigmature.put("analysisiCode","200");
return veriftySigmature;
}
@Override
protected String asyncService(Map<String, String> verifySignature) {
log.info(">>>>>>>>>第三步asyncService()verifySignatureMap:{{}}",verifySignature);
String aliPayMentStatus = verifySignature.get("aliPayMentStatus");
if("1".equals("aliPayMentStatus")){
String aliOrderNumber = verifySignature.get("aliOrderNumber");
log.info(">>>>>>>>>>>>>>{aliOrderNumber},已经支付成功 修改订单状态已经支付。。。。。");
}
return resultSucces();
}
/*
*调用失败情况
* @return
*/
@Override
protected String resultFail() {
//返回失败
return "失败";
}
/**
* 调用成功情况
* @return
*/
@Override
protected String resultSucces() {
return "成功";
}
}
小米支付实现:
/**
* 阿里支付实现
*/
@Slf4j
@Component
public class XiaoMiPayCallbackTemplete extends AbstraractPayCallbackTemplete {
@Override
protected Map<String, String> veriftySigmature() {
//ali支付伪代码 假设一下为阿里支付pay回调报文>>>>>
log.info(">>>>>>>>>>第一步 解析小米报文。。。。。。。。。。veriftySigmature");
Map<String,String> veriftySigmature = new HashMap<>();
veriftySigmature.put("price","899");
veriftySigmature.put("orderDes","商品名称");
//支付状态为1表示成功
veriftySigmature.put("xiaomiPayMentStatus","1");
//支付唯一流水号
veriftySigmature.put("xiaomiOrderNumber","20211111929292");
//解析报文是否成功 假设200是成功
veriftySigmature.put("analysisiCode","200");
return veriftySigmature;
}
@Override
protected String asyncService(Map<String, String> verifySignature) {
log.info(">>>>>>>>>第三步asyncService()verifySignatureMap:{{}}",verifySignature);
String aliPayMentStatus = verifySignature.get("aliPayMentStatus");
if("1".equals("aliPayMentStatus")){
String aliOrderNumber = verifySignature.get("aliOrderNumber");
log.info(">>>>>>>>>>>>>>{aliOrderNumber},已经支付成功 修改订单状态已经支付。。。。。");
}
return resultSucces();
}
/*
*调用失败情况
* @return
*/
@Override
protected String resultFail() {
//返回失败
return "失败";
}
/**
* 调用成功情况
* @return
*/
@Override
protected String resultSucces() {
return "成功";
}
}
定义获取bean对象的工具类
@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);
}
}
定义获取bean对象的Bean工厂
/**
* 获取bean对象的Bean工厂
*/
public class TemplateFactory {
/**
* 使用工厂模式去获取魔板
* @param template
* @return
*/
public static AbstraractPayCallbackTemplete getPayCallBackTemplate(String template){
AbstraractPayCallbackTemplete payCallbackTemplete = (AbstraractPayCallbackTemplete) SpringUtils.getBean(template);
return payCallbackTemplete;
}
}
最后我们来写个Controller层调用下:
@RestController
@RequestMapping("/async")
public class TemplateController {
@PostMapping("/asyncCallBack")
public String asyncCallBack(@RequestBody HashMap<String, String> map){
String templateId = map.get("templateId");
AbstraractPayCallbackTemplete payCallBackTemplate = TemplateFactory.getPayCallBackTemplate(templateId);
return payCallBackTemplate.asyncCallBack();
}
}
日志输出:
我们来总结下优缺点:
优点:模板方法模式通过把不变的行为搬移到超类(父类),去除了子类中的重复代码,子类实现算法的某些细节,有助于算法的扩展,通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合开放-封闭原则。
缺点:每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加吃抽象。
使用场景:在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。