简介
模板方法模式主要用在某个任务的执行步骤一定,但是由不同实体去执行这个任务的时候,每个步骤的具体实现不一样。这样说可能很抽象,举一个实际的例子,比如一个电商网站上很常见的订单付款任务,这个任务执行的步骤基本可以分为两步,第一步计算总价,第二步发起付款。这个任务的执行步骤固定,但是使用支付宝和使用微信的时候第二步的实现明显是完全不一样的,这个时候就可以使用模板方法模式
用法
下面就针对上面举的例子简单介绍一下模板方法的具体用法
public class Order {
private Integer amount; //数量
private BigDecimal price; //单价
private String payChannel; //支付渠道
public Order(Integer amount, BigDecimal price, String payChannel) {
this.amount = amount;
this.price = price;
this.payChannel = payChannel;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getPayChannel() {
return payChannel;
}
public void setPayChannel(String payChannel) {
this.payChannel = payChannel;
}
}
首先定义一个订单类,只有这个例子需要的几个属性
public abstract class BasePay {
public boolean payOrder(Order order){
//第一步计算总价
BigDecimal totalPrice = calculateTotalPrice(order);
//第二步发起支付
return realPay(totalPrice);
}
//真实付款
protected abstract boolean realPay(BigDecimal totalPrice);
private BigDecimal calculateTotalPrice(Order order) {
return order.getPrice().multiply(new BigDecimal(order.getAmount()));
}
}
这里定义模板方法的抽象类,定位支付任务的执行步骤。第一步计算总价,第二步发起支付。第一步计算总价实现都是一样的,所以抽象类也可以说是基类直接实现,第二步不同的支付方式具体实现不一样,所以定义为抽象方法,由具体支付方式实现。
public class AliPay extends BasePay{
@Override
protected boolean realPay(BigDecimal totalPrice) {
System.out.println("支付宝支付:"+totalPrice.toPlainString());
return true;
}
}
public class WxPay extends BasePay{
@Override
protected boolean realPay(BigDecimal totalPrice) {
System.out.println("微信支付:"+totalPrice.toPlainString());
return true;
}
}
分别实现支付宝和微信两种支付方式,这里具体过程忽略。接下来就是怎么取使用以及后续如何扩展
public class OrderService {
private static Map<String,BasePay> payChannelMap = new HashMap<>();
public static void main(String[] args) {
payChannelInit();
Order order1 = new Order(2,new BigDecimal(11.3f),"ali");
payOrder(order1);
Order order2 = new Order(5,new BigDecimal(22.3f),"wx");
payOrder(order2);
}
private static boolean payOrder(Order order) {
return payChannelMap.get(order.getPayChannel()).payOrder(order);
}
private static void payChannelInit() {
payChannelMap.put("ali",new AliPay());
payChannelMap.put("wx",new WxPay());
}
}
定义不同的订单实体,然后根据订单的支付渠道这个属性获取对应的支付方式,然后支付订单。如果这时候再接入一个银联支付,实现也很简单,也不用改动原来的代码,增加一个银联支付的实现类,加入支付渠道的集合中就可以了,这里也充分体现了开闭原则,对扩展开发,对修改关闭。银联实现如下
public class UnionPay extends BasePay{
@Override
protected boolean realPay(BigDecimal totalPrice) {
System.out.println("银联支付:"+totalPrice.toPlainString());
return true;
}
}