(learn&think)

不浮躁,不自傲,学习,思考,总结

浅谈设计模式十: 模板方法模式(Template Method)

| Comments

1 实例

有些人喜欢喝茶,有些人喜欢喝咖啡,所以现在有咖啡和茶两个类,基本代码如下:

Coffee 类:

class Coffee {
 public:
  virtual ~Coffee();
  void prepareRecipe();
 protected:
  void boilWater();
  void brewCoffeeGrinds();
  void pourInCup();
  void addSugarAndMilk();
};

Tea 类:

class Tea {
 public:
  virtual ~Tea();
  void prepareRecipe();
 protected:
  void boilWater();
  void steepTeaBag();
  void pourInCup();
  void addLemon();
};

我们发现代码有重复: void boilWater()void pourInCup() 。那么如何整合代码消除重复代码呢?

2 模板方法模式(Template method)

2.1 目的

为操作中的算法定义一个构架,把一些步骤延迟到子类来完成。模板方法让子类能不改变算法框架的前提下重定义这算法的一些步骤。

2.2 实现

2.2.1 提取不变,抽象变化

提取出不变的地方,在基类类定义并实现,然子类共同拥有,抽象变化地方为抽象接口,延迟到让子类来实现。

class CaffeineBeverage {
 public:
  virtual ~CaffeineBeverage();
  void prepareRecipe();
 protected:
  void boilWater();
  void pourInCup();
  virtual void brew() = 0;
  virtual void addCondiments() = 0;
};

2.2.2 Coffee 类实现自己功能

Coffee 类继承基类 CaffeineBeverage ,并实现抽象接口来完成自己的算法功能。

class Coffee : public CaffeineBeverage {
 public:
  virtual ~Coffee();
 protected:
  virtual void brew();
  virtual void addCondiments();
};

void Coffee::brew() {
  cout << "Dripping Coffee through filter" << endl;
}

void Coffee::addCondiments() {
  cout << "Adding Sugar and Milk" << endl;
}

2.2.3 Tea 类实现自己功能

Tea 类继承基类 CaffeineBeverage ,并实现抽象接口来完成自己的算法功能。

class Tea : public CaffeineBeverage {
 public:
  virtual ~Tea();
 protected:
  virtual void brew();
  virtual void addCondiments();
};

void Tea::brew() {
  cout << "Steeping the tea" << endl;
}

void Tea::addCondiments() {
  cout << "Adding Lemon" << endl;
}

2.2.4 总的模式设计

3 总结

3.1 模板方法模式(Template method)结构

3.2 组成

  • 抽象类(AbstractClass)
    1. 定义抽象的原语操作,具体子类将重定义它们来实现算法的步骤。
    2. 实现一个模板方法定义一个算法的构架。模板方法调用原语操作和抽象类或其他对象定义的操作。
  • 具体类(ConcreteClass)实现原语操作来执行算法中子类特有的步骤。

3.3 应用场景

  • 一次性实现一个算法的不变部分,把变化部分留给子类去实现。
  • 各子类间的共同行为需要被提取并集中到一个共同的类中来避免代码的重复。你首先识别出这些现有代码的不同之处,然后把这些不同之处分离到新的操作中。最后,你用一个模板方法调用这些新操作之一来替代原有那些不同的代码。
  • 控制子类扩展。你能定义一个只在特定点调用 hook 操作的模板方法,以此只允许子类在这些点扩展。

Comments