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); }