模版方法模式
模版方法模式
定义一个操作中的算法的框架,而将一些步骤延迟到了子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。
案例
我们拿做饭的例子来说明。比如就做个西红柿鸡蛋吧。我们可以简单地定义一下步骤:
-
第一步:放油
-
第二步:放鸡蛋
有两个厨师,好厨师和坏厨师,虽然好厨师和坏厨师的手法大不相同,但是执行顺序都是一样的,都是先放油再放鸡蛋。
uml
代码
/**
* Cooker模版
*/
public abstract class Cooker {
public abstract void egg();
public abstract void oil();
/**
* 注意这里用final修饰
* 子类不能重写
*/
final public void cook() {
oil();
egg();
System.out.println("大公告成");
}
}
public class GoodCooker extends Cooker {
@Override
public void egg() {
System.out.println("放入适量鸡蛋");
}
@Override
public void oil() {
System.out.println("放入适量油");
}
}
优缺点
优点:
(1)把不可改变的封装起来,把能够改变的扩展开来
(2)他把很多类的共同操作给封装了起来,利于维护
(3)其实我们发现,我们在定义行为时候都是由父类去定义,然后子类去实现即可。
缺点:
缺点很简单,我们发现虽然我们把一些类的共同操作封装了起来,但是当这些类比较多时,效果就不好了,因为有一个拓展子类都需要继承它,子类多了就不好了。
钩子函数
钩子就是给子类一个授权,让子类来决定模板方法的逻辑执行。就比如在炒西红柿鸡蛋的时候,由子类去决定是否要加调料。我们去实现一下:
/**
* Cooker模版
*/
public abstract class Cooker {
public abstract void egg();
public abstract void oil();
public boolean addSalt() {
return false;
}
/**
* 注意这里用final修饰
* 子类不能重写
*/
final public void cook() {
oil();
egg();
if (addSalt()) {
System.out.println("放入盐");
} else
System.out.println("不放入盐");
System.out.println("大公告成");
}
}
子类就可以设置其逻辑是否执行。