小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
需求
国庆长假结束了,领导也都休假完回来上班了,一到公司看到我闲着没事干,就给我安排了个任务。要我做一个支付模块提供给其他的业务系统使用,要求兼容多种支付渠道。话不多说,上号!
概述
模板方法模式,是一种行为设计模式。在一个抽象类中定义了执行的方法/模板,子类按需重写需要实现的不同逻辑,调用时以抽象类中定义的方式运行。
适用场景
- 多个子类拥有相同的方法,且逻辑部分相似度高。
- 核心的或者复杂的方法需要被反复调用,可以考虑做为模板方法。
角色
抽象模板:定义一个或多个抽象方法,让子类实现具体逻辑。同时在当前类中定义好算法框架,实现对抽象方法的调度,完成固定的逻辑。
具体实现:给出抽象方法的不同实现,使得抽象模板中逻辑可得到不同的实现。
代码实现
抽象模板:因为抽象类不能注入到容器中,所以这里多了一层PaymentService
来实现模板部分,具体的抽象方法定义在了BasePayment
抽象类中。同时还定义了一个枚举类,用来获取对应的bean
。
public class PaymentService {
@Autowired
private ApplicationContext applicationContext;
/**
* 支付请求
* @param type 支付类型
* @return java.lang.String
*/
public final String pay(String type, String params){
System.out.println("解密验签");
// 其它固定的逻辑
// 通过容器得到实例
BasePayment basePayment = getPaymentBean(PayModel.valueOf(type).getServiceName());
String result = basePayment.doPay(params);
System.out.println("加签加密");
// 返回结果
return result;
}
/**
* 查询请求
* @param type 支付类型
* @return java.lang.String
*/
public final String query(String type, String params){
System.out.println("解密验签");
// 其它固定的逻辑
// 通过容器得到实例
BasePayment basePayment = getPaymentBean(PayModel.valueOf(type).getServiceName());
String result = basePayment.doQuery(params);
System.out.println("加签加密");
// 返回结果
return result;
}
/**
* 退款请求
* @param type 支付类型
* @return java.lang.String
*/
public final String refund(String type, String params){
System.out.println("解密验签");
// 其它固定的逻辑
// 通过容器得到实例
BasePayment basePayment = getPaymentBean(PayModel.valueOf(type).getServiceName());
String result = basePayment.doRefund(params);
System.out.println("加签加密");
// 返回结果
return result;
}
/**
* 获取Bean
*
* @param serviceName 服务名
* @return BasePayment
*/
public BasePayment getPaymentBean(String serviceName){
return (BasePayment)applicationContext.getBean(serviceName);
}
}
复制代码
public abstract class BasePayment {
/**
* 支付请求
*
* @param params 支付参数
* @return java.lang.String
*/
protected abstract String doPay(String params);
/**
* 查询请求
*
* @param params 查询参数
* @return java.lang.String
*/
protected abstract String doQuery(String params);
/**
* 退款请求
*
* @param params 退款参数
* @return java.lang.String
*/
protected abstract String doRefund(String params);
}
复制代码
public enum PayModel {
/**
* 微信
*/
WX_PAY("weiXinPayment"),
/**
* 支付宝
*/
AL_PAY("aliPayment"),
/**
* 收款码
*/
SCAN_PAY("scanPayment"),
/**
* 付款码
*/
SWEPT_PAY("sweptPayment"),
/**
* 银联
*/
YL_PAY("ylPayment");
private String serviceName;
PayModel(String serviceName) {
this.serviceName = serviceName;
}
public String getServiceName() {
return serviceName;
}
}
复制代码
具体实现: 实现了微信支付,商家收款码支付,用户付款码支付等多种支付方式,每种支付方式所需的参数不同,处理逻辑也不同。
@Service("weiXinPayment")
public class WeiXinPayment extends BasePayment{
/**
* 微信预付单
*
* @param params 支付参数
* @return java.lang.String
*/
@Override
protected String doPay(String params) {
// 设置必要参数,发起预付单请求获取 prepaid
return "微信预付单:" + params;
}
/**
* 微信支付状态查询
*
* @param params 查询参数
* @return java.lang.String
*/
@Override
protected String doQuery(String params) {
return "微信支付状态查询:" + params;
}
/**
* 微信支付退款
*
* @param params 退款参数
* @return java.lang.String
*/
@Override
protected String doRefund(String params) {
return "微信支付退款:" + params;
}
}
复制代码
@Service("scanPayment")
public class ScanPayment extends BasePayment {
/**
* 收款码申请
*
* @param params 支付参数
* @return java.lang.String
*/
@Override
protected String doPay(String params) {
// 申请动态收款二维码
return "收款码申请:" + params;
}
/**
* 收款码支付结果查询
*
* @param params 查询参数
* @return java.lang.String
*/
@Override
protected String doQuery(String params) {
return "收款码支付结果查询:" + params;
}
/**
* 收款码支付退款
*
* @param params 退款参数
* @return java.lang.String
*/
@Override
protected String doRefund(String params) {
return "收款码支付退款:" + params;
}
}
复制代码
@Service("sweptPayment")
public class SweptPayment extends BasePayment{
/**
* 付款码支付
*
* @param params 支付参数
* @return java.lang.String
*/
@Override
protected String doPay(String params) {
// 根据用户付款码进行扣款
return "付款码支付:" + params;
}
/**
* 付款码支付结果查询
*
* @param params 查询参数
* @return java.lang.String
*/
@Override
protected String doQuery(String params) {
return "付款码支付结果查询:" + params;
}
/**
* 付款码支付退款
*
* @param params 退款参数
* @return java.lang.String
*/
@Override
protected String doRefund(String params) {
return "付款码支付退款:" + params;
}
}
复制代码
案例结果:这里为了演示将具体实现中返回结果修改成为控制台打印
public class TemplateMethodPattern {
public static void main(String[] args) {
PaymentService paymentService = new PaymentService();
paymentService.pay("WX_PAY", "openid");
System.out.println("=================================");
paymentService.pay("SCAN_PAY", "price");
System.out.println("=================================");
paymentService.pay("SWEPT_PAY", "PaymentCode");
}
}
复制代码
小结
优点
- 封装不变部分,扩展可变部分
- 提取公共代码,便于维护
- 行为由父类控制,子类实现
缺点
- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!!!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!