模板模式的主要应用场景为:
一、在软件的构造过程种,它经常有稳定的总体操做,但各个子步骤却有着不少改变的需求,或者因为固有的缘由二没法与任务的总体框架同时实现;其定义一个操做中的算法骨架,而将一些步骤延迟(变化的部分)到子类中,模板的方法使得子类能够不改变(复用)一个算法的结果便可重定义该算法的某些特定步骤。
二、更为通俗的说法是,在父类中实现某个通用的流程,具体小的实现步骤在各个特定的子类中实现,这样增强了代码的复用,可是使用本设计模式的前提是存在一成不变的通用流程。ios
从图中可与看出来存在两个抽象类Document、Application,其中Document用于对文档进行各种操做,固然起也是抽象类,由于对于不一样的文档须要细化操做细节,咱们仅看用于实现抽象操做一个文件的Application类,其具体的操做流程以下所示:算法
首先判断这个文件是否能够被打开,随后使用DoCreateDocument()来产生处理文档的特定类MyDocument,以便实现对不一样文件的不一样操做,最后经过一系列流程来完成打开过程。值得注意的是OpenDocument()中逻辑过程是稳定的不变的,其中每一步的具体实现是变化的,所以将OpenDocument设置为非虚的成员函数,而将组成OpenDocument的子步骤,也就是CanOpenDocument()、AddDocument()、AboutToOpenDocument()与DoCreateDocument()设置为虚的成员函数。设计模式
一、一次性实现一个算法的不变部分,并将可变的行为留给子类来实现;
二、各子类中公共的行为应被提取出来并集中到一个公共父类中以免代码重复;
三、控制子类扩展。框架
一、使用C++访问控制 在C++中,一个模板方法调用的可变化的那些操做能够被定义为保护成员。这保证他们只在模板方法中被调用(封装原则,反正具体的实现步骤都须要封装在一个特定的对外方法中,如前面的OpenDocument()方法中)。必须被重定义的可变化的成员函数必须被定义为纯虚函数,模板自身不需被重定义;所以将这个模板方法定义为一个非虚成员函数。
二、尽可能减小须要重定义的部分 本方法原本就是将主要的工做交给库的设计者(父类),而子类做为直接的方法使用者无需掌握繁杂的使用流程,若须要重定义大量方法不就违反了这个规则。函数
#ifndef TEMPLATE_H #define TEMPLATE_H #include<iostream> #include<string> using std::string; class Abstract_class { public: Abstract_class(double re = 0, double img = 0) :re(re), img(img) {}; virtual ~Abstract_class(); void run() { step1(); step2(); step3(); step4(); } private: double re; double img; virtual void step1(string s=" ") = 0; virtual void step2(string s = " ") = 0; virtual void step3(string s = " ") = 0; virtual void step4(string s = " ") = 0; }; Abstract_class::~Abstract_class() { std::cout << "触发Abstract_class析构函数" << std::endl; } class Concretclass1:public Abstract_class { private: double re; double img; void step1(string s) ; void step2(string s) ; void step3(string s) ; void step4(string s) ; public: Concretclass1(double re = 0, double img = 0) :re(re), img(img) {}; virtual ~Concretclass1() { std::cout << "触发Concretclass1析构函数" << std::endl; }; }; void Concretclass1::step1(string s) { std::cout << "this is step1:+:" <<(re+img)<< std::endl; } void Concretclass1::step2(string s) { std::cout << "this is step2:-:" <<(re - img) << std::endl; } void Concretclass1::step3(string s) { std::cout << "this is step3:*:" << (re * img) << std::endl; } void Concretclass1::step4(string s) { std::cout << "this is step4:/:" << (re /img) << std::endl; } #endif // !TEMPLATE_H
在代码中咱们定义了一个抽象类Abstract_class,这个类中包含一个该子类的通用处理流程run,可是run里面的子实施流程是由各个子类实现的,所以根据以前的说法run方法应该设为public且非虚的,他的子实施流程应该设为private且是虚的(由于外界对象不须要看到这个方法,只须要看到run就好了,增长了封装性)。
在子类Concretclass1中咱们实现了这些子实施流程,随后直接使用run()方法就达到目的了。.c文件的内容为:this
#include"template.h" int main() { Concretclass1* p1 = new Concretclass1(1.0, 2.0); p1->run(); delete p1; std::cin.get(); }
输出结果为:spa
能够看到经过在Concretclass1调用从Abstract_class继承的run()方法,成功的使用了子类的重定义的方法,虽然说优点不怎么明显哈哈。设计