2018-09-21 18:42:07ios
模板(Template)模式,定义一个操做中算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。算法
AbstractClass:一个抽象模板,定义抽象的原语操做(PrimitiveOperation),具体的子类将重定义它们,以便有针对性的实现算法的各个步骤。另外,它还将实现一个模板方法(TemplateMethod),这是一个具体方法,它将给出一个顶级的逻辑框架,而逻辑的组成步骤在相应的抽象操做中,推迟到子类实现,顶级逻辑也有可能调用定义在AbstractClass类或者其它地方的具体方法。框架
ConcreteClass:实现父类所定义的一个或多个抽象方法,每个AbstractClass均可以有任意多个ConcreteClass与之对应,而每个ConcreteClass均可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不一样实现,从而使得顶级逻辑的实现各不相同。ide
模板模式经过把整个继承体系中不变的地方移动到基类,变化的部分以虚函数的形式给出,将实现延迟到子类,这样就达到了在子类中去除重复代码(那些全部子类都同样的代码)的目的。经过模板方法能很好的达到代码复用的目的,那么客户代码在使用这个模板的时候,只须要经过ConcreteClass的实例来调用TemplateMethod就能够实现多样化的计算结果了。函数
模板方法适用场景spa
1.当遇到一个由一系列步骤构成的过程须要执行,但这个过程从高层上看是相同的,但有些步骤的实现可能不一样,而有一些是相同的(把这些相同的方法设计为模板方法或者其它父类的具体方法)。这个时候就能够考虑使用模板模式了。设计
2.经过子类来决定算法中的某个步骤是否须要执行,达到经过子类对父类进行反向控制的目的。code
优势blog
1.在父类中形式化的定义一个算法(TemplateMethod),而由其子类实现具体的细节,在子类中实现算法的具体处理细节时不会影响算法的操做次序(这是次序是在TemplateMethod中定义好的)继承
2.这是一种代码复用技术,在设计类库时,能够把整个类库的公共部分抽离到父类中,经过子类来实现差别化的行为。
3.能够实现子类对父类的反向控制(不太懂),经过覆盖父类的钩子方法来决定某一特定步骤是否须要执行。
4.在模板方法模式中,能够经过子类来覆盖父类的基本方法,不一样的子类能够提供这些基本方法的不一样实现。更换和增长新的子类是符合开放封闭原则的。
缺点:
每一个不一样的实现都须要提供一个子类,若是变化太多会形成子类数量过多。看下代码示例的客户代码就很明了这句话的意思了
人早晨起床的流程:要先睁眼(这个每一个人都是固定的方式,至于有人微睁,有人半睁就不要纠结了。。。)、起床、洗漱、(睁眼、起床、洗漱每一个人都同样)吃饭(但吃饭,每一个人的早餐都是不一样的)。
1.AbstractClass
#ifndef ABSTRACTCLASS_H_ #define ABSTRACTCLASS_H_ #include <iostream> #include <string> class AbstractClass { public: void openEyes() { std::cout << "I opened my eyes!" << std::endl; } void getUp() { std::cout << "I got up!" << std::endl; } virtual void wash() { std::cout << "I had washed." << std::endl; } virtual void eatBreakfast() = 0; virtual void templateMethod() { openEyes(); getUp(); wash(); eatBreakfast(); } AbstractClass() = default; virtual ~AbstractClass() = default; }; #endif
2.ConcreteClass
#ifndef CONCRETECLASS_H_ #define CONCRETECLASS_H_ #include "AbstractClass.h" #include <string> class ConcreteClass:public AbstractClass { public: void eatBreakfast(); ConcreteClass() = default; ~ConcreteClass() = default; private: }; #endif #include "ConcreteClass.h" void ConcreteClass::eatBreakfast() { std::cout << "default eat eggs" << std::endl; } #ifndef CONCRETECLASSYANGYANG_H_ #define CONCRETECLASSYANGYANG_H_ #include "AbstractClass.h" class ConcreteClassYangyang : public AbstractClass { public: void eatBreakfast() override; ConcreteClassYangyang() = default; ~ConcreteClassYangyang() = default; }; #endif #include "ConcreteClassYangYang.h" void ConcreteClassYangyang::eatBreakfast() { std::cout << "Yang yang ate noodles." <<std::endl; }
3.Client
#include "ConcreteClass.h" #include "ConcreteClassYangYang.h" using namespace std; int main(int argc,char *argv[]) { AbstractClass *obj1 = new ConcreteClass; obj1->templateMethod(); if(nullptr != obj1) { delete obj1; obj1 = nullptr; } AbstractClass *obj2 = new ConcreteClassYangyang; obj2->templateMethod(); if(nullptr != obj2) { delete obj2; obj2 = nullptr; } return (1); }