模板方法模式的定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
设计原则:别调用我们,我会调用你,(就好比猎头和求职者,求职者不需要去找猎头,猎头只要有工作就会找到你)称之为好莱坞原则
引用一个例子,一个店中有两饮料:咖啡和茶,他们的冲泡方法
第一步:都是要用沸水
第二步:用热水泡咖啡或茶
第三步:把饮料倒进杯子
第四步:在饮料中加入适当的调料
在上面的步骤中一、三是一样的,可以抽取出来放在基类中,二、四不一样,可以抽象出来,让子类去实现,以下是饮料抽象的父类,父类可以让未知的子类去做它本身可能完成的不好或者根本完成不了的事情;可以加一个钩子函数:custcomerWantsCondiments(),请子类去重写。
CoffeineBeverageWithHook.java
package com.dzt.template; /** * 由于有的客户有可能不需要调料,这时就需要让客户去选择是否来添加调料,需要 * * @author Administrator * */ public abstract class CoffeineBeverageWithHook { void prepareRecipe() { boilWater(); brew(); pourInCup(); if (custcomerWantsCondiments()) addCondiments(); } abstract void brew(); // 冲泡 abstract void addCondiments(); // 添加调料 // 烧开水 void boilWater() { System.out .println("CoffeineBeverageWithHook-------------------->boilWater"); } // 把饮料倒进杯子 void pourInCup() { System.out .println("CoffeineBeverageWithHook-------------------->pourInCup"); } /** * 子类可以重载这个函数 * * @return */ boolean custcomerWantsCondiments() { return true; } }
以下是咖啡类,继承了上面的饮料父类
CoffeineWithHook.javapackage com.dzt.template; public class CoffeineWithHook extends CoffeineBeverageWithHook { @Override void brew() { // TODO Auto-generated method stub System.out.println("CoffeineWithHook-------------------->brew"); } @Override void addCondiments() { // TODO Auto-generated method stub System.out .println("CoffeineWithHook-------------------->addCondiments"); } @Override boolean custcomerWantsCondiments() { // TODO Auto-generated method stub return false; } }
以下是茶类,继承了上面的饮料父类
package com.dzt.template; public class TeaWithHook extends CoffeineBeverageWithHook { @Override void brew() { // TODO Auto-generated method stub System.out.println("TeaWithHook-------------------->brew"); } @Override void addCondiments() { // TODO Auto-generated method stub System.out.println("TeaWithHook-------------------->addCondiments"); } @Override boolean custcomerWantsCondiments() { // TODO Auto-generated method stub return true; } }
以上代码可以去修改custcomerWantsCondiments()函数,由用户决定是否需要添加调料
测试代码
package com.dzt.template; /** * 模板方法模式 在模板方法中添加钩子方法,让用户决定 * * @author Administrator * @date 2014.08.20 */ public class TemplateMain { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub CoffeineWithHook coffHook = new CoffeineWithHook(); TeaWithHook teaHook = new TeaWithHook(); coffHook.prepareRecipe(); System.out .println("---------------------------------------------------------------"); teaHook.prepareRecipe(); } }
总结:
1、模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。
2、模板方法导致一种方向控制结构,"好莱坞法则":"Don‘t call me,i will call you.",即一个父类调用子类的操作,而不是相反。
3、模板调用操作的类型有具体的操作,具体的AbstracClass操作,原语操作,工厂方法,钩子操作。少定义原语操作。
4、模板方法使用继承来改变算法的一部分。策略模式使用委托来改变整个算法。
相关代码:http://download.csdn.net/detail/deng0zhaotai/7835511
参考书籍:《Head First 设计模式》