详解设计模式中的模板方法模式及在C++中的使用

慢慢来
慢慢来
发布时间:2026-10-14| 6人浏览过
原创

模板方法模式是行为型设计模式中结构最清晰的一种。它通过定义一个操作中的算法骨架,将一些步骤延迟到子类中实现,使得子类在不改变算法结构的前提下即可重定义特定步骤。本文将深入解析其核心概念,并通过C++代码示例演示如何在实际开发中应用。

什么是模板方法模式

模板方法模式(Template Method Pattern)的核心在于“封装变化”。它将不变的部分(算法骨架)封装在父类中,而将变化的部分(具体实现)留给子类去扩展。这种模式不仅实现了代码复用,还符合面向对象设计中的开闭原则和依赖倒置原则。

该模式主要包含以下两个角色:

  • AbstractClass(抽象类):定义抽象的原语操作(钩子),实现一个模板方法以定义算法的骨架。
  • ConcreteClass(具体子类):实现原语操作,以完成算法中与特定子类相关的步骤。

以下是该模式的通用结构图:

C++ 实战:试卷答题示例

为了直观理解,我们设定一个场景:老师需要为几十个学生出具期末试卷。试卷的大部分题目内容是一致的,唯一的区别在于学生的姓名和每道题的具体答案。

在这种场景下,我们可以将“做试卷”这个流程抽象为一个基类。试卷的题目顺序(算法骨架)由基类固定,而填写姓名和回答问题的具体内容由各个学生(子类)根据自己的情况来实现。

第1步:定义抽象基类

首先,我们创建 TestPaper 类。在这个类中,我们定义了做题的整体流程 DoTestPaper(),以及具体的题目展示逻辑。其中,涉及学生个性化填写的部分(如名字、答案)被声明为纯虚函数,强制子类必须实现。

class TestPaper 
{ 
public: 
  // 模板方法:定义算法骨架 
  void DoTestPaper(){ 
    StudentName();       // 学生填写姓名 
    TestTitleOne();      // 题目一流程 
    TestTitleTwo();      // 题目二流程 
  } 
 
  // 具体方法:展示题目标题,调用虚函数获取答案 
  void TestTitleOne(){ 
    cout << "题目一:X国的房价会降下来么?" << endl; 
    AnswerOne();         // 延迟到子类实现 
  } 
 
  void TestTitleTwo(){ 
    cout << "题目二:说说你的新闻联播的看法?" << endl; 
    AnswerTwo();         // 延迟到子类实现 
  } 
 
  // 抽象方法:由子类实现具体细节 
  virtual void AnswerOne() = 0;
  virtual void AnswerTwo() = 0;
  virtual void StudentName() = 0;
}; 

第2步:创建具体子类(以小红为例)

接下来,我们创建一个继承自 TestPaper 的 XiaoHongTestPaper 类。小红不需要关心试卷的整体结构,她只需要填写自己的名字,并对两道题目给出自己的观点。

class XiaoHongTestPaper : public TestPaper 
{ 
public: 
  void StudentName(){ 
    cout << "姓名:小红" << endl;
  }
  void AnswerOne(){ 
    cout << "答:相信X,相信国家,明年一定降下来。" << endl << endl;
  }
  void AnswerTwo(){ 
    cout << "答:新闻联播是我最喜欢的节目啊。" << endl << endl;
  }
}; 

第3步:创建另一个具体子类(以小张为例)

同样地,我们可以创建 XiaoZhangTestPaper 来代表另一位学生。虽然题目骨架相同,但小张的答案和态度可能与小红完全不同,这体现了模板方法模式对具体步骤的扩展能力。

class XiaoZhangTestPaper : public TestPaper 
{ 
public: 
  void StudentName(){ 
    cout << "姓名:小张" << endl;
  }
  void AnswerOne(){ 
    cout << "答:呵呵,还是去做你的X国梦吧。" << endl << endl;
  }
  void AnswerTwo(){ 
    cout << "答:我很幸福" << endl << endl;
  }
}; 

第4步:客户端调用测试

在主函数中,我们可以分别实例化小红的试卷和小张的试卷,并调用 DoTestPaper() 方法。可以看到,尽管底层逻辑完全一致,但输出的结果因子类而异。

int main(int argc, char* argv[]) 
{ 
  XiaoHongTestPaper paper1;
  paper1.DoTestPaper();
 
  XiaoZhangTestPaper paper2;
  paper2.DoTestPaper();
 
  system("pause");
  return 0;
} 

深入讨论:优缺点与应用场景

依赖倒置原则(DIP)的体现

模板方法模式获得了一种反向控制结构的效果,这也是面向对象设计中依赖倒置原则(Dependency Inversion Principles)的典型应用。其含义是:父类(高层模块)调用子类(低层模块)的操作,而低层模块实现了高层模块声明的接口。这样控制权掌握在父类手中,低层模块反而依赖于高层模块。

继承的局限性

尽管模板方法模式简单易用,但它基于继承机制,这也带来了固有的限制:

  1. 子类耦合度高:对于 ConcreteClass 中的实现的原语方法,无法被其他类复用。
  2. 难以组合变体:假设我们需要创建一个新的算法变体 AnotherAbstractClass,并且希望复用现有子类中的某些原语操作。由于子类已经继承自原始抽象类,它们无法再继承 AnotherAbstractClass,导致无法灵活复用。

替代方案:策略模式

为了解决继承带来的灵活性不足问题,策略模式(Strategy Pattern) 是一个更好的替代方案。策略模式通过组合(委托)的方式,将算法家族封装起来并在运行时切换,避免了继承的刚性约束。当然,其代价通常是增加了空间和时间上的开销(对象创建和指针间接调用)。在实际开发中,应根据具体需求权衡选择模板方法或策略模式。

以上就是C++中模板方法模式的详细内容,更多关于设计模式实践的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。