设计模式(12) - Template模板方法模式
来源:互联网 发布:淘宝怎么打印发货清单 编辑:程序博客网 时间:2024/05/16 12:50
1. Intent
模板方法模式定义了某个操作中所用算法的框架,而把算法的具体实现步骤推迟到了子类中。这样,模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。这个模式就是用于创建一个算法模板的。那么什么是模板?
它只是一个方法,一个将算法定义为一系列操作步骤的方法。这些步骤中的一个或者多个会被定义为抽象接口,子类去实现它。这就确保了当子类去实现具体步骤时,算法的结构不会被更改。
2. UML classes
参考上面图表:
类AbstractClass包含了模板方法。模板方法中使用了操作的抽象版本。
可能存在很多的ConcreteClasses类, 每一个类中都实现了模板方法所需要的所有操作集合。
类ConcreteClasses实现了抽象操作,当templateMethod()需要它们时,它们就会被调用到。
模板方法利用primativeOperations来实现一个算法。这样可以和这些操作的具体实现进行解耦。
3. Example A
//template.h#ifndef _TEMPLATE_H_#define _TEMPLATE_H_#include <iostream>using namespace std;namespace ShltshDesignPatterns {namespace Template{class AbstractClass{public:void templateMethod(){primitiveOperation1();primitiveOperation2();concreteOperation();hook();}virtual void primitiveOperation1()=0;virtual void primitiveOperation2()=0;void concreteOperation(){cout<<"Mandatory Operations for all ConcreteClasses"<<endl;}virtual void hook(){}};class ConcreteClassA:public AbstractClass{public:void primitiveOperation1(){cout<<"primitiveOp1 A"<<endl;}void primitiveOperation2(){cout<<"primitiveOp2 A"<<endl;}};class ConcreteClassB:public AbstractClass{public:void primitiveOperation1(){cout<<"primitiveOp1 B"<<endl;}void primitiveOperation2(){cout<<"primitiveOp2 B"<<endl;}void hook(){cout<<"hook B"<<endl;}};}}#endif//main.cpp#include "template.h"using namespace ShltshDesignPatterns::Template;int main(){ConcreteClassA ca;ConcreteClassB cb;ca.templateMethod();cb.templateMethod();system("pause");return 0;}运行结果:
primitiveOp1 A
primitiveOp2 A
Mandatory Operations for all ConcreteClasses
primitiveOp1 B
primitiveOp2 B
Mandatory Operations for all ConcreteClasses
hook B
Press any key to continue . . .
基于上面的结果,可以总结如下:
1).函数templateMethod()定义了步骤的顺序,每个步骤由一个方法实现。
2).下面的这两个原始操作必须在具体的子类中实现。
virtual void primitiveOperation1() = 0;
virtual void primitiveOperation2() = 0;
3). 下面的这个具体操作是在抽象类中定义的。这个方法没有定义成虚函数(virtual),这样子类就不能覆写(override)它。它可能被模板方法直接使用,或者子类使用。
void concreteOperation() { cout<<"Mandatory Operations for all ConcreteClasses" << endl; }
4). 我们也可以创建具体方法,但是这些方法不做什么事情,称为hooks。子类可以自由选择是否覆写它们。
virtual void hook() {}
4. Example B
下面的这个例子中,有两个具体类,继承自OperationTemplate类,这个父类提供了3个接口:read_input(), write_output, 以及 operate()。两个子类在共用这些接口的同时,各自i实现了不同的操作。这就是模板方法模式所能提供的能力。//template.h#ifndef _TEMPLATE_H_#define _TEMPLATE_H_#include<iostream>#include<algorithm>#include<cassert>#include<iterator>#include<list>#include<map>#include<sstream>#include<string>#include<utility>using namespace std;namespace ShltshDesignPatterns{namespace Template{class OperationTemplate{public:typedef std::map<std::string, std::string> Arguments;bool solve(const Arguments &input, Arguments &output){assert(output.empty());if(!read_input(input))return false;if(!operate())return false;write_output(output);return true;}protected:virtual bool read_input(const Arguments &input) = 0;virtual bool operate() = 0;virtual void write_output(Arguments &output)const = 0;};class MathOperation:public OperationTemplate{public:MathOperation():mx(0),my(0),mOperation(0),mResult(0){ }private:bool read_input(const Arguments &input){Arguments::const_iterator iter = input.find("x");if(input.end() == iter)return false;std::istringstream in(iter->second);in >> mx;if(in.fail())return false;iter = input.find("y");if(input.end() == iter)return false;in.clear();in.str(iter->second);in>>my;if(in.fail())return false;iter=input.find("operation");if(input.end()==iter || iter->second.size()!=1)return false;mOperation = iter->second[0];return true;}bool operate(){switch (mOperation){case '+':mResult = mx + my;break;case '-':mResult = mx - my;break;case '*':mResult = mx * my;break;case '/':if (0 == my) {return false;}mResult = mx / my;break;default:return false;}return true;}void write_output(Arguments &output) const{std::ostringstream out;out << mResult;output.insert(std::make_pair(std::string("result"), out.str()));}private:int mx,my,mResult;char mOperation;};class ListOperation : public OperationTemplate{private:bool read_input(const Arguments &input){mList.clear();Arguments::const_iterator i = input.find("array");if (input.end() == i) {return false;}std::istringstream in(i->second);typedef std::istream_iterator<int> T;std::copy(T(in), T(), std::back_inserter(mList));if (!in.eof()) return false;return true;}bool operate(){mList.reverse();return true;}void write_output(Arguments &output) const{std::ostringstream out;std::copy(mList.begin(), mList.end(),std::ostream_iterator<int>(out, " "));output.insert(std::make_pair(std::string("result"), out.str()));}private:std::list<int> mList;};}}#endif//main.cpp#include "template.h"using namespace ShltshDesignPatterns::Template;int main(){ map<string, string> myInput, myOutput; // 10 + 20 = 30 myInput.insert(make_pair("x", "10")); myInput.insert(make_pair("y", "20")); myInput.insert(make_pair("operation", "+")); MathOperation a; a.solve(myInput, myOutput); cout << myOutput["result"] << endl; myInput.clear(); myOutput.clear(); // 1 2 3 4 5 -> 5 4 3 2 1 myInput["array"] = "1 2 3 4 5"; ListOperation b; b.solve(myInput, myOutput); cout << myOutput["result"] << endl; system("pause");return 0;}运行结果:
30
5 4 3 2 1
Press any key to continue . . .
0 0
- 设计模式(12) - Template模板方法模式
- 模板方法(Template)设计模式
- 设计模式之模板方法模式Template
- 设计模式----模板方法模式(Template Method)
- [设计模式]模板方法模式(Template Method)
- 设计模式--模板方法模式Template
- 【设计模式】-模板方法模式(Template)
- [C++设计模式]template 模板方法模式
- 设计模式:模板方法模式(Template)
- 设计模式:模板方法模式-template method
- 设计模式 模板方法模式 Template Method
- 设计模式-模板方法模式-template-python
- 设计模式(12)-模板方法模式(Template Method)
- Template(模板)设计模式
- 设计模式----Template Method(模板方法)
- 设计模式学习-Template Method(模板方法)
- 【设计模式】之 Template 模板方法
- 设计模式之Template Method (模板方法)
- 设计模式(8) - Composite组合模式
- HTML DOM Style 对象介绍
- 设计模式(9) - Flyweight享元模式
- 设计模式(10) - Facade外观模式
- 设计模式(11) - Proxy代理模式
- 设计模式(12) - Template模板方法模式
- 设计模式(13) - Strategy策略模式
- Android_Loader_使用LoaderManager管理Loader实现异步动态加载数据
- 设计模式(14) - State状态模式
- 设计模式(15) - Observer观察者模式
- 十五章
- 设计模式(16) - Mementor备忘录模式
- 设计模式(17) - Mediator中介者模式
- 设计模式(18) - Command命令模式