这篇文章介绍一种笔者认为最最最简单的设计模式,模板方法模式。
0.抛出问题
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体架构同时实现。如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?
1.具体场景
举个栗子,现在我们用机器自动生产汉堡,通常来说汉堡的结构是确定的,两层面包中间夹上食材,不过有时候中间的食材可能是生菜,猪肉、牛肉、鸡肉、半鸡半虾(说的我好饿= =)。所以我们就可以定一个抽象类的汉堡,为一个汉堡模板,假设我们的汉堡结构为面包+生菜+肉+面包。代码如下
public abstract class Hamburger {
public final void getHamburger(){
topBread();
lettuce();
meat();
bottomBread();
}
protected void topBread(){
System.out.println("上面的面包");
}
protected void lettuce(){
System.out.println("中间的生菜");
}
protected abstract void meat();
protected void bottomBread(){
System.out.println("底部的面包");
}
}
给getHamburger加上final的原因是防止子类错误的复写,如果复写为一个汉堡上层是生菜,中间是两片面包,底层是肉饼,就不符合逻辑了...
现在我们要做一个深海鳕鱼堡
public class CodFishBurger extends Hamburger {
@Override
protected void meat() {
System.out.println("深海鳕鱼");
}
}
测试类
public class Test {
public static void main(String[] args)
{
Hamburger codFishBurger=new CodFishBurger();
codFishBurger.getHamburger();
}
}
\\测试结果
上面的面包
中间的生菜
深海鳕鱼
底部的面包
Process finished with exit code 0
这时候如果我们需要一个新奥尔良汉堡或者一个田园脆鸡堡,我们只需要写出相应的类去继承抽象汉堡类。
在这里顺便告诉大家一个冷知识,肯德基或者麦当劳是可以根据你的需求去做汉堡的,在点汉堡的时候我们可以告诉点餐员不加生菜等需求。
在模板方法中,我们需要一个勾子,去根据需求决定是否去调用某个的方法。
修改代码如下
public abstract class Hamburger {
private boolean lettuceHook = true;//默认是有生菜的
protected void setLettuceHook(boolean lettuceHook) {//根据需求决定是否加生菜
this.lettuceHook = lettuceHook;
}
public final void getHamburger() {
topBread();
if (lettuceHook)
lettuce();
meat();
bottomBread();
}
protected void topBread() {
System.out.println("上面的面包");
}
protected void lettuce() {
System.out.println("中间的生菜");
}
protected abstract void meat();
protected void bottomBread() {
System.out.println("底部的面包");
}
}
测试类
public class Test {
public static void main(String[] args)
{
System.out.println("第一个汉堡:");
Hamburger codFishBurger=new CodFishBurger();
codFishBurger.getHamburger();
System.out.println("第二个汉堡:");
Hamburger codFishBurger2=new CodFishBurger();
codFishBurger2.setLettuceHook(false);
codFishBurger2.getHamburger();
}
}
//测试结果
第一个汉堡:
上面的面包
中间的生菜
深海鳕鱼
底部的面包
第二个汉堡:
上面的面包
深海鳕鱼
底部的面包
2.要点总结
优点:灵活地实现具体的算法,满足用户灵活多变的需求
缺点:算法骨架需要改变时需要修改抽象类
模板方法模式是一种非常基础性的设计模式,在面向对象中有着大量的应用(如java的HttpServlet)。它用最简洁的机制(抽象函数的多态性)实现为很多应用框架提供了灵活的扩展点,是代码复用方面的基本实现结构。除了可以灵活应对子步骤变化外,“不要调用我,让我来调用你”的反向控制结构是模板方法的典型应用。