模板方法模式

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


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


下面是咖啡的代码:

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() {
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值