对于模板方法模式,我想说的是,每个写过代码的人都应该或多或少的用过,它的定义为:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。说的通俗一点,就是为子类设计一个模板以便于子类复用里面的方法。为了避免子类恶意修改方法的实现细节,一般模板方法模式都会在方法上加final。
来一个简单的例子吧,小明离职自己创业开了个蛋糕店,蛋糕店不能只卖一种蛋糕呀,于是小明决定先卖奶油蛋糕,芝士蛋糕和慕斯蛋糕。三种蛋糕如果分别做那也太麻烦了,起码造型,烘焙和涂抹蛋糕上的东西都差不多是一样的。所以可以定义一个抽象蛋糕模型
public abstract class AbstractCake{ protected abstract void shape(); protected abstract void apply(); protected abstract void brake(); }
下面就可以批量生产三种蛋糕咯
class CreamCake extends AbstractCake { @Override protected void shape() { System.out.println("奶油蛋糕造型"); } @Override protected void apply() { System.out.println("奶油蛋糕涂抹"); } @Override protected void brake() { System.out.println("奶油蛋糕烘焙"); } } class CheeseCake extends AbstractCake { @Override protected void shape() { System.out.println("芝士蛋糕造型"); } @Override protected void apply() { System.out.println("芝士蛋糕涂抹"); } @Override protected void brake() { System.out.println("芝士蛋糕烘焙"); } } class MouseCake extends AbstractCake { @Override protected void shape() { System.out.println("慕斯蛋糕造型"); } @Override protected void apply() { System.out.println("慕斯蛋糕涂抹"); } @Override protected void brake() { System.out.println("慕斯蛋糕烘焙"); } }
这样一来,不但可以批量生产三种蛋糕,而且如果日后有扩展,只需要继承抽象蛋糕方法就可以了,十分方便,小明天天生意做得越来越赚钱。突然有一天,小明看到对面店铺的蛋糕店卖的一种最简单的小蛋糕销量很好,这种蛋糕就是简单烘烤成型就可以卖,并不需要涂抹什么食材,由于制作简单销售量大,那家店靠这个品种赚了许多钱,于是小明也想要生产这种蛋糕。但是小明发现了一个问题,抽象蛋糕是定义了抽象的涂抹方法的,也就是说扩展的这种蛋糕是必须要实现涂抹方法,这就很鸡儿蛋疼了。思来想去,小明不得其中三昧,于是就去问他师傅,他师傅疾言厉色:不带钩子方法的模板都是耍流氓!小明就仿佛吃了一颗九转大还丹,简直是茅塞顿开,于是他回去做了这么个修改
abstract class AbstractCake{ protected boolean shouldApply(){ return true; } protected abstract void shape(); protected abstract void apply(); protected abstract void brake(); public final void run(){ this.shape(); if(this.shouldApply()){ this.apply(); } this.brake(); } }
然后做小蛋糕的时候通过flag来控制是否涂抹
class SmallCake extends AbstractCake { private boolean flag = false; public void setFlag(boolean shouldApply){ flag = shouldApply; } @Override protected boolean shouldApply() { return this.flag; } @Override protected void shape() { System.out.println("小蛋糕造型"); } @Override protected void apply() { System.out.println("小蛋糕涂抹"); } @Override protected void brake() { System.out.println("小蛋糕烘焙"); } }
虽然这里有模板方法,但是通过钩子方法还是能够影响到模板方法的执行(不是影响它的逻辑)。小明又开开心心做起了生意。。