Spring中使用模板方法模式(接上文)

接上一篇文章末尾提出的扩展点,本次进行实现。上文链接:Spring项目中使用策略模式+工厂模式

改动

  1. 以下是之前的PayService接口,之前为了举例,只是简单写了两个方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* PayService
*
* @author ZXP
* @date 2021/12/4 21:23
*/
public interface PayService {

/**
* 支持的支付类型
*
* @return
*/
PayEnum getPayType();

/**
* 具体的支付逻辑
*
* @param obj
*/
void pay(Object obj);
}
  1. 本次演示模板方法模式,再添加如下的业务方法,sign() 为签名方法,微信支付和支付宝支付都需要先进行签名再请求接口,每个实现类签名方法略有不同,所以交由具体实现类实现,createOrder() 为创建订单方法,doPay() 为支付主方法,业务处主要调用的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* PayService
*
* @author ZXP
* @date 2021/12/4 21:23
*/
public interface PayService {

/**
* 支持的支付类型
*
* @return
*/
PayEnum getPayType();

/**
* 签名
*
* @param obj
* @return
*/
String sign(Object obj);

/**
* 创建订单
*
* @param obj
*/
void createOrder(Object obj);

/**
* 具体的支付逻辑
*
* @param obj
*/
void pay(Object obj);

/**
* 支付主方法
*
* @param obj
*/
void doPay(Object obj);
}
  1. 增加抽象实现类AbstractPayServiceImpl,该类位于PayService接口与AliPayServiceImpl等具体实现类中间,为 createOrder() 等逻辑相同的方法提供默认实现,并在 doPay() 主方法中将各个方法调用逻辑组织起来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Service
public abstract class AbstractPayServiceImpl implements PayService {

@Override
public void createOrder(Object obj) {
// 创建订单的逻辑
System.out.println(String.format("创建%s类型的订单", getPayType().getEn()));
}

/**
* 主方法,里边组织各个方法的调用逻辑
*
* @param obj
*/
@Override
public void doPay(Object obj) {

// 1.签名,各个支付商签名方式可能不一样,所以交由各个子类实现
sign(obj);

// 2.创建订单,创建订单的逻辑大致一致,可以在抽象类中实现,如有不一致的可再子类中重写
// 默认调用抽象类中实现的
createOrder(obj);

// 3.支付的逻辑,各个支付商签名方式可能不一样,所以交由各个子类实现
pay(obj);
}
}
  1. 修改具体实现类继承抽象类,并重写抽象方法,由于createOrder() 在抽象类中已提供默认实现,所以具体子类中不需要重写,如果默认实现满足不了某个子类,则子类可以进行重写。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 支付宝支付处理类
*
* @author ZXP
* @date 2021/12/4 21:29
*/
@Service
public class AliPayServiceImpl extends AbstractPayServiceImpl {

@Override
public PayEnum getPayType() {
return PayEnum.ALIPAY;
}

/**
* 支付宝支付的签名逻辑
*
* @param obj
* @return
*/
@Override
public String sign(Object obj) {
return "testAliPaySign";
}

@Override
public void pay(Object obj) {
// 支付宝支付的逻辑
System.out.println("使用了支付宝支付");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 微信支付处理类
*
* @author ZXP
* @date 2021/12/4 21:28
*/
@Service
public class WxPayServiceImpl extends AbstractPayServiceImpl {

@Override
public PayEnum getPayType() {
return PayEnum.WX;
}

/**
* 微信支付的签名逻辑
*
* @param obj
* @return
*/
@Override
public String sign(Object obj) {
return "testWxSign";
}

@Override
public void pay(Object obj) {
// wx支付逻辑
System.out.println("使用了微信支付");
}
}

使用演示

1
2
3
4
5
6
@Test
public void testPay() {
// 调用doPay()支付主方法
PayServiceFactory.get(PayEnum.WX).doPay(new Object());
PayServiceFactory.get(PayEnum.ALIPAY).doPay(new Object());
}

执行结果

执行结果

总结

引入模板方法模式将支付主逻辑在doPay() 主方法中进行实现,其中各个子方法的实现可能有相同也可能有不同,根据需求在AbstractPayServiceImpl中来选择是否重写,如果未重写则子类必须重写;已重写的方法,子类可以根据默认方法是否满足自身需求来选择是否需要重写,从而使得代码耦合度降低,并且可读性也有所提升,每个类的职责单一,不至于太过复杂。