前言
本篇聊聊模板方法模式。
正文
概念
模板方法模式属于行为型模式,它定义一个模板结构,然后让其子类去实现。其主要作用是提高代码的复用性,并且在不改变模板的情况下子类能重写方法。
那这种设计模式就十分常见了,在父类中定义执行顺序,子类再去具体的去实现,这就是模板方法模式。
实现
举个例子,比如我们平常去超市买东西,基本上分为几个步骤,拿购物车或篮子,挑选商品,结算。那就用这个例子来写写代码。
未使用模板方法模式
首先我们一般来说我们是先定义一个父类,然后子类再去实现父类方法。也就是没使用模板方法模式时,我们可能会这么写:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public abstract class AbstractClass { public abstract void getShoppingCart();
public abstract void selectGoods();
public abstract void pay();
public abstract void shopping(); }
|
那在子类当中,我们可能这么写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class ShoppingByOnlinePay extends AbstractClass{ @Override public void getShoppingCart() { System.out.println("获取购物车"); }
@Override public void selectGoods() { System.out.println("挑选商品"); }
@Override public void pay() { System.out.println("使用网上支付"); }
@Override public void shopping() { getShoppingCart(); selectGoods(); pay(); } }
|
那这样写就是在抽象类中不写任何逻辑,所有的实现都在子类中实现,如果后续有问题也较好发现,但我们可以发现,其实shopping方法是固定的,也就是流程固定,那么我们这些代码是不是可以移动到抽象类中呢?是的,可以,这就是模板方法模式。
使用模板方法
我们重写下抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public abstract class AbstractClass { protected abstract void getShoppingCart();
protected abstract void selectGoods();
protected abstract void pay();
public final void shopping(){ this.getShoppingCart(); this.selectGoods(); this.pay(); } }
|
我们将子类需要重写的方法定义为protected,因为这些方法不需要暴露给其他类,只需要子类自己实现即可,然后我们把购物流程在抽象类中以final修饰,因为流程固定不需要修改。
我们接着写现金付款和网上支付两种结算方式的类。
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
| public class ShoppingByOnlinePay extends AbstractClass{ @Override protected void getShoppingCart() { System.out.println("获取购物车"); }
@Override protected void selectGoods() { System.out.println("挑选商品"); }
@Override protected void pay() { System.out.println("使用网上支付"); } } public class ShoppingByCash extends AbstractClass{ @Override protected void getShoppingCart() { System.out.println("获取购物车"); }
@Override protected void selectGoods() { System.out.println("挑选商品"); }
@Override protected void pay() { System.out.println("使用现金结算"); } }
|
那这里调用就很简单,我就不写了,直接调用shopping方法即可。
如此,我们就使用模板方法模式实现了这个简单的例子。
优缺点
模板方法模式具有良好的封装性,即把一成不变的代码封装在父类当中,而子类去实现基本方法的逻辑,并且扩展性良好,符合开闭原则和单一职责原则。那最重要的还是复用了重复代码。
那缺点嘛,可能就是实现类都需要单独的子类去实现,可能会增加类的数量,但我个人认为这个其实严格来说不能说是缺点,除非是实现的种类存在几十种上百种。当然,仁者见仁智者见智,算不算缺点只有在用到的时候才能知道。