模板方法模式

来源:互联网 发布:南京网络问政回复时间 编辑:程序博客网 时间:2024/06/18 17:59

模板方法模式定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。


以一个冲咖啡和冲茶的实例来说明,它们都有类似的步骤:煮沸水、冲咖啡(茶)、倒进杯子、加调料。


下面是咖啡的代码:

public class Coffee  {   void PrepareRecipe(){       boilWater();       brewCoffeeGrinds();       pourInCup();       addSugerAndMilk();   }   public void addSugerAndMilk() {       System.out.println("Adding Suger and Milk");   }   public void pourInCup() {       System.out.println("Pouring into Cup");   }   public void brewCoffeeGrinds() {       System.out.println("Dripping coffee through filter");   }   public void boilWater() {       System.out.println("Boiling Water");   }}

茶的代码:

public class Tea  {   void PrepareRecipe(){       boilWater();       steepTeaBag();  //这是泡茶专有的方法       pourInCup();       addLemon();     //这是泡茶专有的方法   }   public void addLemon() {       System.out.println("Adding lemon");   }   public void steepTeaBag() {       System.out.println("Steeping the tea");   }   public void pourInCup() {       System.out.println("Pouring into Cup");   }   public void boilWater() {       System.out.println("Boiling Water");   }}

这两个类中有许多相同的代码,我们可以将其抽离,新建一个抽象类CaffeineBeverage:


public abstract class CaffeineBeverage {   final void perpareRecipe(){  //我们不希望子类覆盖这个方法。       boilWater();       brew();       pourInCup();       addCondiments();   }   protected abstract void addCondiments();   private void pourInCup() {       System.out.println("Pouring in Cup");   }   protected abstract void brew();   private void boilWater() {       System.out.println("Boiling Water");   }}

于是上面的两个coffee与tea类可以改成:

public class Tea extends CaffeineBeverage{   @Override   protected void addCondiments() {       System.out.println("Adding Lemon");   }   @Override   protected void brew() {       System.out.println("Steeping the Tea");   }}public class Coffee extends CaffeineBeverage {   @Override   protected void addCondiments() {       System.out.println("adding suger and milk");   }   @Override   protected void brew() {       System.out.println("dripping coffee through filter");   }}



我们做的工作:将冲泡的方法放到基类中,它是一个算法的模板。某些方法是由这个类处理的(第一个与第三个),某些方法是由子类实现处理的(第二个与第四个)。


这样做的好处:

由CaffeineBeverage类主导一切,它拥有算法,而且保护这个算法。

对子类来说,CaffeineBeverage的存在,可以将代码的复用最大化。

算法只存在于一个地方,所以很容易修改(一开始存在于两个文件中,如果修改要修改两处)。

如果新的咖啡因饮料加进来,只需要实现自己独有的方法就可以了。

CaffeineBeverage类专注在算法本身,而由子类提供完整的实现。



模板方法模式的具体定义:模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。


这就是模板方法:


final void perpareRecipe(){   boilWater();   brew();   pourInCup();   addCondiments();}

它被声明为final,以免子类改变这个算法的顺序。



钩子:

我们可以有”默认不做事的方法”,我们称这种方法为hook。子类可以视情况决定要不要覆盖它们。
final void perpareRecipe(){   boilWater();   brew();   pourInCup();   addCondiments();   hook();}private void hook() {}

钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类来决定。钩子可以让子类有能力为其抽象类作一些决定。

原创粉丝点击