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

基本概念

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

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

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

  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,即模板方法模式在已有的算法骨架下支持一定的拓展。

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

相关推荐
蜀黍@猿5 分钟前
C/C++基础错题归纳
c++
雨中rain20 分钟前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
ALISHENGYA1 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
arong_xu2 小时前
现代C++锁介绍
c++·多线程·mutex
汤姆和杰瑞在瑞士吃糯米粑粑2 小时前
【C++学习篇】AVL树
开发语言·c++·学习
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
CodeClimb2 小时前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
奶香臭豆腐3 小时前
C++ —— 模板类具体化
开发语言·c++·学习
不想当程序猿_3 小时前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
cdut_suye3 小时前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python