前言
本文中所有设计模式Github代码
其中本文模板方法相关代码在TemplateMethodPattern.h
文件中
一、模板方法基础
1. 模板方法的提出
对于某项具体任务,模板方法模式常常拥有稳定的整体操作结构,但各个子步骤的具体实现可能各不相同(改变的)。那么如何在稳定的操作结构前提下,灵活应变各个子步骤的变化或者晚期实现需求?
2.
模板方法的设计思想&&代码实现(C++)
已知在程序开发中,框架开发人员(程序库开发人员)常常会提供一些稳定的操作结构和方法,而一些可变的具体的操作步骤则由应用开发人员来实现。这种情况下,框架开发人员可以使用模板方法模式来实现
2.1 模板方法使用场景示例
假设我们需要设定一系列步骤step1~step5来实现某项功能,其中step1、step3、step5的实现是稳定的,可以在程序库lib开发中实现
但是step2和step4的实现是不稳定的,需要在应用开发中实现
而整体的step1~step5的步骤顺序和使用框架是稳定的
2.2
未使用模板方法的代码实现思路
当我们没有采用模板方法模式时,我们会在程序库lib开发中提供step1、step3、step5的稳定实现,然后在应用开发中提供step2和step4的不稳定实现。最后在main程序中实现step1~step5的调用来实现具体功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> using namespace std;
class Library{ public: void step1(){ cout << "Library::step1()" << endl; } void step3(){ cout << "Library::step3()" << endl; } void step5(){ cout << "Library::step5()" << endl; } };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Application { public: bool step2(){ cout << "Application::step2()" << endl; return true; } void step4(){ cout << "Application::step4()" << endl; } };
int main(){ Library lib; Application app;
lib.step1();
if(app.step2()){ lib.step3(); }
for(int i = 0; i < 4; i++){ app.step4(); }
lib.step5();
return 0; }
|
这种方法属于早绑定的实现方式,在结构化的设计思维,也就是晚实现的应用程序人员开发程序去调用更早实现的lib库
这种实现方法是有缺点的:对于稳定的step1~step5的调用是分散的,不利于维护
2.3 使用模板方法的代码实现思路
解决上述问题的方法思路是:
将稳定的main函数中的整体步骤实现也放在稳定的程序库lib中,然后在应用开发中实现不稳定的步骤
由于lib库中也需要用到app的实现,因此我们可以将两个不稳定的函数作为lib库的虚函数,交由应用程序开发人员继承实现
这样在main中直接创建一个lib库的多态指针,然后调用lib的整体实现步骤框架函数就可以
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <iostream> using namespace std;
class Library{ public: void step1(){ cout << "Library::step1()" << endl; } void step3(){ cout << "Library::step3()" << endl; } void step5(){ cout << "Library::step5()" << endl; } void run(){ step1(); if(step2()){ step3(); } for(int i = 0; i < 4; i++){ step4(); } step5(); } virtual bool step2() = 0; virtual void step4() = 0; virtual ~Library(){}; };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Application:public Library { public: bool step2(){ cout << "Application::step2()" << endl; return true; } void step4(){ cout << "Application::step4()" << endl; } };
int main(){ Library* plib = new Application(); plib->run(); delete plib; return 0; }
|
这种方法属于晚绑定的实现方式,是面向对象开发的设计思维,也就是早实现的lib库通过开发稳定的算法骨架(Run函数),并将一些步骤延迟(延迟也就是虚函数)到晚实现的应用程序开发人员去实现
二、总结
在面向对象的设计中,我们要将稳定的代码写成非虚函数,将不稳定的代码写成虚函数,这样可以实现稳定代码的复用,不稳定代码的延迟实现
设计模式的假设是必须有一个稳定点,那么当所有代码都是不稳定的时候,就不适合使用设计模式了
设计模式最大的特点是在变化和稳定中间寻找隔离点,将变化的部分通过虚函数隔离出来,使得稳定的部分不受影响
虚函数是面向对象里面最核心的晚绑定实现技术