转载请注明出处:http://blog.youkuaiyun.com/droyon/article/details/8685227
模板方法:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法就是一个方法,将方法的实现设计成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以保证算法的结构保持不变,同时由子类提供部分实现。
案例情景:
把老虎关进冰箱,总共分几步?三步,第一步把冰箱门打开,第二部把老虎塞进冰箱,第三部,把冰箱门关上。这是宋丹丹和赵本山小品中的一个冷幽默。我们依照此情景,来实现我们的模板方法。
CloseObjectToFridge.java
public abstract class CloseObjectToFridge {
final void closeObject(){
openFridge();
takeObjectToFridge();
closeFridge();
if(isFreeze()){
freeze();
}
}
void openFridge(){
System.out.println("把冰箱门打开");
}
abstract void takeObjectToFridge();
void closeFridge(){
System.out.println("把冰箱门关上");
}
boolean isFreeze(){//钩子
return true;
}
void freeze(){
System.out.println("冷冻储藏");
}
}
CloseMeat.java
public class CloseMeat extends CloseObjectToFridge{
@Override
void takeObjectToFridge() {
System.out.println("把肉类放进冰箱");
}
}
CloseTigger.java
public class CloseTigger extends CloseObjectToFridge{
@Override
void takeObjectToFridge() {
System.out.println("把老虎塞进冰箱");
}
}
Test.java
public class Test {
public static void main(String args[]){
CloseObjectToFridge closeMeat = new CloseMeat();
CloseObjectToFridge closeTigger = new CloseTigger();
closeMeat.closeObject();
System.out.println("--------------------------------");
closeTigger.closeObject();
}
}
测试结果:
把冰箱门打开
把肉类放进冰箱
把冰箱门关上
冷冻储藏
--------------------------------
把冰箱门打开
把老虎塞进冰箱
把冰箱门关上
冷冻储藏
这里有一个问题,肉可以冷冻储藏,老虎冷冻储藏,老虎就死了,所以我们在老虎类中,复写isFreeze方法。在设计时ifFreeze方法是一个钩子,一个在运行中方便将部分逻辑放到子类去实现的一个架构。
public class CloseTigger extends CloseObjectToFridge{
@Override
void takeObjectToFridge() {
System.out.println("把老虎塞进冰箱");
}
@Override
boolean isFreeze() {
// TODO Auto-generated method stub
return false;
}
}
测试结果:
把冰箱门打开
把肉类放进冰箱
把冰箱门关上
冷冻储藏
--------------------------------
把冰箱门打开
把老虎塞进冰箱
把冰箱门关上
钩子能够作为条件控制,影响抽象类的算法流程。钩子是一种方法,它在抽象类中不做事,或者做默认的事,子类可以选择要不要去覆盖它。
好莱坞规则:别调用我们,我们会调用你。我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些低层组件。
模板方法存在很多变体,也有很多应用,比如android中的activity,打印时重写toString方法,比较时compareTo方法,高层组件都会默认加载这些方法。
模板方法为我们提供了一种代码复用的技巧。
模板模式和策略模式都封装算法,一个用组合,一个用继承。
工厂方法是模板方法的一个特殊版本。