原文:http://computerdragon.blog.51cto.com/6235984/1167937
模板方法模式定义为:在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中去实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某一些步骤。
模板方法在基类中定义了一个操作的流程顺序,能够保证该步骤按序进行,有一些步骤的具体实现在基类中已经声明,而将一些变化的步骤的具体实现交给了子类去实现,从而就达到了延迟一些步骤到子类中,模板方法一个最大的好处就是能够设定一个业务流程能够按照一定严格的顺序执行,控制了整个算法的执行步骤。
这个方法将算法定义成一组步骤,其中凡是想让子类进行自定义实现的步骤,均定义为抽象方法。抽象基类的特点是,一般将模板方法设置为final,这样防止子类覆盖该算法的步骤,将一些相同的操作或步骤直接在基类中实现,将一些变化的步骤设置为抽象由子类去完成。
代码实例:
假如要泡杯茶和咖啡,要想泡咖啡则需要先将水煮沸,然后用沸水冲泡咖啡,将咖啡倒进杯子,加糖和牛奶。要想泡茶叶则需要把水煮沸,然后用沸水冲茶叶,将茶倒入杯子,放点柠檬。
通过分析,这些操作基本上都是四步骤,顺序都是固定的,且有相同的步骤,则就可以利用模板方法来将泡饮料的过程制作一个算法的骨架,将变化的部分抽象出来,让具体的子类去实现。
抽象超类,这个类是负责泡饮料的基类,设置了算法的骨架
<span style="color:#330033;">package com.whut.modelmethod;
//模板方法
abstract class BeverageMake {
//final可以防止子类更改覆盖该算法,这样可以保证算法步骤不被破坏
public final void prepareRecipe()
{
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew();
abstract void addCondiments();
//烧水
publicvoid boilWater()
{
System.out.println("Now start to boiling water");
}
//饮料导入杯子汇总
publicvoid pourInCup()
{
System.out.println("pour the beverage into the cup");
}
}</span>
具体的类,茶叶类:
package com.whut.modelmethod;
publicclass Tea extends BeverageMake {
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("boil the tea in the water");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("put some condiments into the tea");
}
}
测试类:
<span style="font-size:18px;">package com.whut.modelmethod;
publicclass MakeTest {
publicstaticvoid main(String[] args) {
Tea tea=new Tea();
tea.prepareRecipe();
}
}</span>
模板方法中挂钩:
重写上面的代码:
这次茶叶泡好后,加不加东西由子类去决定
超类:
<span style="font-size:18px;">package com.whut.modelmethod;
//模板方法
abstractclass BeverageMake {
//final可以防止子类更改覆盖该算法,这样可以保证算法步骤不被破坏
public final void prepareRecipe()
{
boilWater();
brew();
pourInCup();
if(hookCondiments())
addCondiments();
}
abstract void brew();
abstract void addCondiments();
//烧水
public void boilWater()
{
System.out.println("Now start to boiling water");
}
//饮料导入杯子汇总
public void pourInCup()
{
System.out.println("pour the beverage into the cup");
}
//加入了钩子,来让子类决定是否执行该步骤
public boolean hookCondiments()
{
returntrue;
}
}
</span>
茶叶子类:
package com.whut.modelmethod;
publicclass Tea extends BeverageMake {
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("boil the tea in the water");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("put some condiments into the tea");
}
//设置不需要加饮料,这样就可以控制算法的某一个步骤不执行
@Override
public boolean hookCondiments()
{
return false;
}
}
设计原则 :
别调用我们,我来调用你们。
这种原则主要就是,我们允许底层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎么样来使用这些底层组件。
要点:
1)钩子是一种方法,它在抽象类中不做事,或者是默认的事情,子类可以选择覆盖它
2)为了防止子类改变模板方法中的算法骨架,一般将模板方法声明为final
3)策略模式和模板方法都是用于封装算法,前者是利用组合和委托模型,而后者则是继承