Java设计模式之模板方法

来源:互联网 发布:个人软件开发合同书 编辑:程序博客网 时间:2024/06/08 09:11

原文: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 {@Overridevoid brew() {// TODO Auto-generated method stubSystem.out.println("boil the tea in the water");}@Overridevoid addCondiments() {// TODO Auto-generated method stubSystem.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 {@Overridevoid brew() {// TODO Auto-generated method stubSystem.out.println("boil the tea in the water");}@Overridevoid addCondiments() {// TODO Auto-generated method stubSystem.out.println("put some condiments into the tea");}//设置不需要加饮料,这样就可以控制算法的某一个步骤不执行@Overridepublic boolean hookCondiments(){return false;}}

设计原则
别调用我们,我来调用你们。
这种原则主要就是,我们允许底层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎么样来使用这些底层组件。
要点:
1)钩子是一种方法,它在抽象类中不做事,或者是默认的事情,子类可以选择覆盖它
2)为了防止子类改变模板方法中的算法骨架,一般将模板方法声明为final
3)策略模式和模板方法都是用于封装算法,前者是利用组合和委托模型,而后者则是继承



0 0