设计模式——模板方法模式

基本概念

模板方法模式是一种行为设计模式, 它在超类(基类)中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

该模式是对于面向过程编程的一种抽象,它定义了一个算法的骨架 ,将一些步骤的实现延迟到子类 。子类在不改变算法结构的情况下,重新定义算法的某些步骤。

比如,做一道菜至少需要三步:

  1. 准备食材
  2. 烹饪
  3. 上菜

虽然不同菜品的烹饪方法和准备过程不同,但是不妨碍我们定义一个算法的"骨架",包含这三个步骤,然后将烹饪过程放到具体的炒菜类去实现,这样无论是吵什么才,都可以亚勇相同的炒菜算法,只需要在子类中实现具体的炒菜步骤就行。模板方法模式提高了代码的可复用性,类似于模板编程。

基本结构

在原来的若干类的基础上,抽象出一个模板方法,定义一个模板抽象类,然后具体类继承自模板类,实现了模板类中定义的抽象方法,去完成算法中的特定步骤。

  • 模板类AbstractClass:由一个模板方法和若干个基本方法构成,模板方法定义了逻辑的骨架,按照顺序去调用包含的基本方法,基本方法同时是一些抽象方法,这些方法由子类去实现。基本方法还包含一些具体方法,他们是算法类的一部分但已经有默认实现,在具体子类可以继承或者重写。
  • 具体类ConcreteClass:继承自模板类,实现了模板类中定义的抽象方法,完成算法中特定步骤的具体实现。
cpp 复制代码
class AbstractClass {
  /**
   * The template method defines the skeleton of an algorithm.
   */
 public:
  void TemplateMethod() const {
    this->BaseOperation1();
    this->RequiredOperations1();
    this->BaseOperation2();
    this->Hook1();
    this->RequiredOperation2();
    this->BaseOperation3();
    this->Hook2();
  }
  /**
   * These operations already have implementations.
   */
 protected:
  void BaseOperation1() const {
    std::cout << "AbstractClass says: I am doing the bulk of the work\n";
  }
  void BaseOperation2() const {
    std::cout << "AbstractClass says: But I let subclasses override some operations\n";
  }
  void BaseOperation3() const {
    std::cout << "AbstractClass says: But I am doing the bulk of the work anyway\n";
  }
  /**
   * These operations have to be implemented in subclasses.
   */
  virtual void RequiredOperations1() const = 0;
  virtual void RequiredOperation2() const = 0;
  /**
   * These are "hooks." Subclasses may override them, but it's not mandatory
   * since the hooks already have default (but empty) implementation. Hooks
   * provide additional extension points in some crucial places of the
   * algorithm.
   */
  virtual void Hook1() const {}
  virtual void Hook2() const {}
};
/**
 * Concrete classes have to implement all abstract operations of the base class.
 * They can also override some operations with a default implementation.
 */
class ConcreteClass1 : public AbstractClass {
 protected:
  void RequiredOperations1() const override {
    std::cout << "ConcreteClass1 says: Implemented Operation1\n";
  }
  void RequiredOperation2() const override {
    std::cout << "ConcreteClass1 says: Implemented Operation2\n";
  }
};
/**
 * Usually, concrete classes override only a fraction of base class' operations.
 */
class ConcreteClass2 : public AbstractClass {
 protected:
  void RequiredOperations1() const override {
    std::cout << "ConcreteClass2 says: Implemented Operation1\n";
  }
  void RequiredOperation2() const override {
    std::cout << "ConcreteClass2 says: Implemented Operation2\n";
  }
  void Hook1() const override {
    std::cout << "ConcreteClass2 says: Overridden Hook1\n";
  }
};
/**
 * The client code calls the template method to execute the algorithm. Client
 * code does not have to know the concrete class of an object it works with, as
 * long as it works with objects through the interface of their base class.
 */
void ClientCode(AbstractClass *class_) {
  // ...
  class_->TemplateMethod();
  // ...
}

int main() {
  std::cout << "Same client code can work with different subclasses:\n";
  ConcreteClass1 *concreteClass1 = new ConcreteClass1;
  ClientCode(concreteClass1);
  std::cout << "\n";
  std::cout << "Same client code can work with different subclasses:\n";
  ConcreteClass2 *concreteClass2 = new ConcreteClass2;
  ClientCode(concreteClass2);
  delete concreteClass1;
  delete concreteClass2;
  return 0;
}
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway

Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway

上述代码源自该C++ 模板方法模式讲解和代码示例,我们来分析一下这个代码的含义。

首先是定义了一个抽象类,定义了公有方法TemplateMethod,按照一定的顺序把所有的类方法都执行一遍。并提供了两个公有函数BaseOperation1BaseOperation2,然后在保护域中定义了四个虚函数,RequireOperation1RequireOperation2是纯虚函数,子类必须实现,还有两个Hook1Hook2是提供了默认的空操作,子类可以选择自己实现。

然后在客户端直接去调用公有方法TemplateMethod,不同的子类的实现方式略有区别,子类1只实现了必要的操作,而子类2还实现了Hook1,即模板方法模式在已有的算法骨架下支持一定的拓展。

综上所述,模板方法模式适用于程式固化的模块,抽象出一个算法"骨架"这样可以方便统一管理,也支持一定的拓展。

相关推荐
螺蛳粉只吃炸蛋的走风16 分钟前
网络编程IO多路复用之poll模式
网络·c++·面试·poll·阻塞与非阻塞
会写代码的饭桶17 分钟前
【C++刷题】力扣-#566-重塑矩阵
c++·leetcode·矩阵
fengbizhe26 分钟前
qt获取本机IP和定位
开发语言·c++·qt·tcp/ip
凯子坚持 c36 分钟前
纵然千万数据流逝,唯独vector长存
c++
何曾参静谧1 小时前
「C/C++」C/C++标准库 之 #include<cstddef> 常用定义和宏
c语言·开发语言·c++
木宇(记得热爱生活)1 小时前
C++ <string> 标头文件详解
开发语言·c++
你有抖音吗2 小时前
【每日 C/C++ 问题】
开发语言·c++
老猿讲编程2 小时前
安全关键型嵌入式系统设计模式整理及应用实例
安全·设计模式·iso26262·do178
lexusv8ls600h3 小时前
微服务设计模式 - 事件溯源模式(Event Sourcing Pattern)
spring boot·微服务·设计模式