介绍:
在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑 (算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用 算法)是相同的。Template 提供了这种情况的一个实现框架。 Template 模式是采用继承的方式实现这一点:将逻辑(算法)框架放在抽象基类中,并 定义好细节的接口,子类中实现细节。【注释 1】
【注释 1】:Strategy 模式解决的是和 Template 模式类似的问题,但是 Strategy 模式是将逻辑 (算法)封装到一个类中,并采取组合(委托)的方式解决这个问题。
结构图:

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

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>
TemplateController
package com.ldq.controller;
import com.ldq.AbstractPayCallbackTemplate;
import com.ldq.factory.TemplateFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Auther: liangdeqiang
* @Date: 2019-5-12 16:10
* @Description:
*/
@RestController
public class TemplateController {
@RequestMapping("/asyncCallBack")
public String asyncCallBack(String templateId){
AbstractPayCallbackTemplate payCallbackTemplate = TemplateFactory.getPayCallbackTemplate(templateId);
return payCallbackTemplate.asyncCallBack();
}
}
TemplateFactory
package com.ldq.factory;
import com.ldq.AbstractPayCallbackTemplate;
import com.ldq.utils.SpringUtils;
/**
* @Auther: liangdeqiang
* @Date: 2019-5-12 16:07
* @Description:
*/
public class TemplateFactory {
/**
* 使用工厂模式获取模板
* @param templateId
* @return
*/
public static AbstractPayCallbackTemplate getPayCallbackTemplate(String templateId){
AbstractPayCallbackTemplate abstractPayCallbackTemplate = SpringUtils.getBean(templateId, AbstractPayCallbackTemplate.class);
return abstractPayCallbackTemplate;
}
}
AliPayCallbackTemplate
package com.ldq.impl;
import com.ldq.AbstractPayCallbackTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: liangdeqiang
* @Date: 2019-5-12 16:02
* @Description:
*/
@Slf4j
@Component
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected String asyncService(Map<String, String> verifySignature) {
log.info(">>>>>第三步 支付宝支付 asyncService()verifySignatureMap:{}", verifySignature);
String paymentStatus = verifySignature.get("aliPayMentStatus");
if (paymentStatus.equals("1")) {
String aliPayOrderNumber = verifySignature.get("aliPayOrderNumber");
log.info(">>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付...");
}
return resultSuccess();
}
private String resultSuccess() {
return "success";
}
@Override
protected String resultFail() {
return "fail";
}
@Override
protected Map<String, String> verifySignature() {
//>>>>假设一下为阿里pay回调报文>>>>>>>>>>>>>>>>
log.info(">>>>>第一步 解析支付宝据报文.....verifySignature()");
Map<String, String> verifySignature = new HashMap<>();
verifySignature.put("price", "1399");
verifySignature.put("orderDes", "充值蚂蚁课堂永久会员");
// 支付状态为1表示为成功....
verifySignature.put("aliPayMentStatus", "1");
verifySignature.put("aliPayOrderNumber", "201910101011");
//>>>>假设一下为阿里pay回调报文结束>>>>>>>>>>>>>>>>
// 解析报文是否成功 或者验证签名成功返回 200 为成功..
verifySignature.put("analysisCode", "200");
return verifySignature;
}
}
UnionPayCallbackTemplate
package com.ldq.impl;
import com.ldq.AbstractPayCallbackTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: liangdeqiang
* @Date: 2019-5-12 16:04
* @Description:
*/
@Slf4j
@Component
public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected String asyncService(Map<String, String> verifySignature) {
log.info(">>>>>第三步 银联回调 asyncService()verifySignatureMap:{}", verifySignature);
String paymentStatus = verifySignature.get("unionPayMentStatus");
if (paymentStatus.equals("1")) {
String aliPayOrderNumber = verifySignature.get("aliPayOrderNumber");
log.info(">>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付...");
}
return resultSuccess();
}
@Override
protected Map<String, String> verifySignature() {
//>>>>假设一下为银联回调报文>>>>>>>>>>>>>>>>
log.info(">>>>>第一步 解析银联据报文.....verifySignature()");
Map<String, String> verifySignature = new HashMap<>();
verifySignature.put("price", "1399");
verifySignature.put("orderDes", "充值蚂蚁课堂永久会员");
// 支付状态为1表示为成功....
verifySignature.put("unionPayMentStatus", "1");
verifySignature.put("unionPayOrderNumber", "201910101011");
//>>>>假设一下为阿里pay回调报文结束>>>>>>>>>>>>>>>>
// 解析报文是否成功 或者验证签名成功返回 200 为成功..
verifySignature.put("analysisCode", "200");
return verifySignature;
}
private String resultSuccess() {
return "ok";
}
@Override
protected String resultFail() {
return "fail";
}
}
SpringUtils
package com.ldq.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@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);
}
}
AbstractPayCallbackTemplate
package com.ldq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @Auther: liangdeqiang
* @Date: 2019-5-12 15:53
* @Description:
*/
@Slf4j
public abstract class AbstractPayCallbackTemplate {
/**
* 定义相同的骨架
* @return
*/
public String asyncCallBack(){
// 1.验证参数和验证签名
Map<String, String> verifySignature = verifySignature();
// 2.日志收集 相同
payLog(verifySignature);
// 3. 获取验证签名状态
String analysisCode = verifySignature.get("analysisCode");
if(!"200".equals(analysisCode)){
return resultFail();
}
// 4.更改数据库状态同时返回不同支付结果
return asyncService(verifySignature);
}
/**
* 提交到数据库获取返回结果
* @param verifySignature
* @return
*/
protected abstract String asyncService(Map<String,String> verifySignature);
/**
* 返回失败结果
* @return
*/
protected abstract String resultFail();
/**
* 执行修改状态和返回不同的结果
* @param verifySignature
*/
@Async
protected void payLog(Map<String,String> verifySignature){
log.info("写入数据库....verifySignature:{}",verifySignature);
}
protected abstract Map<String,String> verifySignature();
}
AppTemplate
package com.ldq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @Auther: liangdeqiang
* @Date: 2019-5-12 16:12
* @Description:
*/
@SpringBootApplication
@EnableAsync
public class AppTemplate {
public static void main(String[] args) {
SpringApplication.run(AppTemplate.class);
}
}
模板方法设计模式提供了一种在抽象基类中定义算法框架,由子类实现具体细节的方式,从而减少了代码重复并遵循了开放-封闭原则。与Strategy模式不同,Template模式采用继承来实现算法的不同变体。此模式适用于需要控制子类扩展且子类必须遵守特定算法逻辑的场景。在实际应用中,例如支付回调处理,可以创建不同的回调模板类(如AliPayCallbackTemplate和UnionPayCallbackTemplate),通过AbstractPayCallbackTemplate进行统一调度。
1095

被折叠的 条评论
为什么被折叠?



