[GoF设计模式]Composite模式和Visitor模式的C++实现

【Composite模式】

 组合模式的关键是抽象类,它既可以代表图元(Leaf),也可以代表图元的容器(Composite)。组合模式可以用于创建树状的结构。用于使用抽象类接口与组合结构中的对象进行交互。如果接收是一个叶结点,则直接处理请求。如果接受者是Composite,它将请求发送给他的子部件,即图元,在转发请求之前或者之后可以进行辅助的操作。组合模式可以用于递归地创建树形结构。组合模式的重点在于构造类,而Decorator模式的重点在于不生成子类即可以给类添加职责。

【图解】一副图片可以由子图片以及图元。如一副图片由线图元、矩形图元、里头还嵌了个子图片,该子图片由文本图元、线图元、矩形图元构成。

 

 

 

 

【程序】

/******************************************************************* * * DESCRIPTION: Graphic Component Class [Abstract Class] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef GRAPHICCOMPONENT_H_ #define GRAPHICCOMPONENT_H_ /** * Base Class * * @author roy nee (2009-9-28) */ class GraphicComponent { public: GraphicComponent(){} virtual ~GraphicComponent(){} virtual void Draw()=0; virtual void Add(GraphicComponent *_component){return;} virtual void Remove(GraphicComponent *_component){return;} virtual GraphicComponent* GetChild(int index){return NULL;} }; #endif  

/******************************************************************* * * DESCRIPTION: PictureComponent Class [inheriated from Base Class] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef PICTURECOMPOSITE_H_ #define PICTURECOMPOSITE_H_ /** include files **/ #include <vector> #include "GraphicComponent.h" using namespace std; /** * Composite Class ,Picture * * @author roy nee (2009-9-28) */ class PictureComposite:public GraphicComponent { public: PictureComposite(){}; virtual ~PictureComposite(){} /// <summary> /// Draw Picture, call its Children's draw() function as the vector Sequence /// </summary> /// <returns></returns> virtual void Draw() { cout<<"/n---PictureComposite: A Picture being drawn......"<<endl; for(vector<GraphicComponent*>::iterator iter=_vecChild.begin();iter!=_vecChild.end();++iter) { (*iter)->Draw(); } cout<<"---PictureComponent: The Picture Complete....../n"<<endl; return; } /// <summary> /// Get the No. index Child's handler /// </summary> /// <param name="index"></param> /// <returns></returns> virtual GraphicComponent * GetChild(int index) { if(index<this->_vecChild.size()) return this->_vecChild[index]; else return NULL; } /// <summary> /// Add a element as his child /// </summary> /// <param name="_component"></param> /// <returns></returns> virtual void Add(GraphicComponent *_component) { if(_component!=NULL) this->_vecChild.push_back(_component); return; } /// <summary> /// Remove a element from his children /// </summary> /// <param name="_component"></param> /// <returns></returns> virtual void Remove(GraphicComponent *_component) { for(vector<GraphicComponent*>::iterator iter=this->_vecChild.begin();iter!=this->_vecChild.end();++iter) { if(_component==(*iter)) { this->_vecChild.erase(iter); return; } } return; } protected: vector<GraphicComponent*> _vecChild; }; #endif  

/******************************************************************* * * DESCRIPTION:Line Class(Concrete Class,inheriated from Base Class) * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef LINELEAF_H_ #define LINELEAF_H_ /** include files **/ #include <iostream> #include "GraphicComponent.h" using namespace std; class LineLeaf:public GraphicComponent { public: /*constructor and destructor*/ LineLeaf(){} virtual ~LineLeaf(){} /*action*/ virtual void Draw() { cout<<"LineLeaf: A Line being Drawn......"<<endl; return; } }; #endif  

/******************************************************************* * * DESCRIPTION: Rectangle Class [Inheriated from Base Class ] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef RECTANGLELEAF_H_ #define RECTANGLELEAF_H_ /** include files **/ #include <iostream> #include "GraphicComponent.h" using namespace std; /** * Rectangle Class * * @author roy nee (2009-9-28) */ class RectangleLeaf:public GraphicComponent { public: RectangleLeaf(){}; virtual ~RectangleLeaf(){} virtual void Draw() { cout<<"RectangleLeaf: A Rectangle being Drawn......"<<endl; return; } }; #endif  

/******************************************************************* * * DESCRIPTION: Text Class [inheriated from Base Class] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef TEXTLEAF_H_ #define TEXTLEAF_H_ /** include files **/ #include <iostream> #include "GraphicComponent.h" using namespace std; /** * Text Class * * @author roy nee (2009-9-28) */ class TextLeaf:public GraphicComponent { public: /*constructor and destructor*/ TextLeaf(){} virtual ~TextLeaf(){} /*action*/ virtual void Draw() { cout<<"TextLeaf: A Text being written......"<<endl; return; } }; #endif  

 

【输出】

[GoF设计模式]Composite模式和Visitor模式的C++实现_第1张图片

 

 

【Visitor模式】

访问者模式的作用是表示作用于某对象结构中的各元素的操作,使得在不改变各元素类的前提下,定义作用于这些元素的新操作。Visitor模式提供了支持单分派(single-dispatch)语言的双分派策略。双分派(double-dispatch or multi-dispatch)是指从两个方面来说的,一个是接收着的型别(即句柄的型别),一个是函数参数运行时候的型别(用RTTI来实现的)。一般的面向对象的语言如C++/JAVA/C#都只支持单分派。这样双分派的实现在C++中可以采用两种方式,一种是函数的重载(即使参数的类别不同),另外一种则是RTTI来实现(通过typeid判断,要用到if...else...等),后者的封装性较差不提倡使用。一般而言使用前者,即函数的重载实现。

【图解】

以下以中国游客和美国游客,去中国或者去美国旅游为例子说明

[GoF设计模式]Composite模式和Visitor模式的C++实现_第2张图片

 

【程序】

程序既给出了重载的方式实现的双分派,也给出了以RTTI方式实现的双分派,注意typeid(*elm)中要传对象参数,而不是指针类型elm,刚开始还弄错了。

/******************************************************************* * * DESCRIPTION: CountryElement Class [Abstract Class] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef COUNTRYELEMENT_H_ #define COUNTRYELEMENT_H_ /** include files **/ #include "Visitor.h" class Visitor; /** * Element Class-[被访问者抽象类] * * @author NeeSky (2009-9-28) */ class CountryElement { public: CountryElement(){} virtual ~CountryElement(){} virtual void AcceptVisitor(Visitor *vis)=0; }; #endif  

/******************************************************************* * * DESCRIPTION:ChinaElement Class[Concrete Class] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef CHINAELEMENT_H_ #define CHINAELEMENT_H_ /** include files **/ #include <iostream> #include "CountryElement.h" #include "Visitor.h" using namespace std; /** * China Place Class * * @author NeeSky (2009-9-28) */ class ChinaElement:public CountryElement { public: /*constructor and destructor*/ ChinaElement(){} virtual ~ChinaElement(){} /*Accept the visitor*/ virtual void AcceptVisitor(Visitor *vis) { cout<<"Now China's place accepted the visitor......"<<endl; return; } }; #endif  

/******************************************************************* * * DESCRIPTION: AmericaElement Class[Concrete Class] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef AMERICAELEMENT_H_ #define AMERICAELEMENT_H_ /** include files **/ #include "CountryElement.h" /** * America Place Class * * @author NeeSky (2009-9-28) */ class AmericaElement:public CountryElement { public: /*constructor and destructor*/ AmericaElement(){} virtual ~AmericaElement(){} /*Accept the Visitor*/ virtual void AcceptVisitor(Visitor *vis) { cout<<"Now America's place accepted the visitor......"<<endl; return; } }; #endif  

/******************************************************************* * * DESCRIPTION:Visitor Class (Abstract Class) * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef VISITOR_H_ #define VISITOR_H_ /** include files **/ #include <typeinfo> //RTTI #include <string> #include "CountryElement.h" #include "ChinaElement.h" #include "AmericaElement.h" class ChinaElement; class AmericaElement; /** * Visitor Class - [访问者抽象类] * * @author roy nee (2009-9-28) */ class Visitor { public: Visitor(){} virtual ~Visitor(){} /*Interface Functions-override functions-singledispatch*/ virtual void visit(ChinaElement *celm)=0; virtual void visit(AmericaElement *aelm)=0; /*RTTI implement the Double-Dispatch*/ virtual void visitRtti(CountryElement *elm)=0; /*Not use RTTI ,C++ not support pure double dispatch */ //virtual void visitDoubleDispatch(CountryElement *elm)=0; }; #endif  

/******************************************************************* * * DESCRIPTION:ChineseVisitor Class [Chinese Visitor] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef CHINESEVISITOR_H_ #define CHINESEVISITOR_H_ /** include files **/ #include <iostream> #include "Visitor.h" #include "AmericaElement.h" #include "ChinaElement.h" using namespace std; /** * Chinese Visitor -[中国人旅游者] * * @author NeeSky (2009-9-28) */ class ChineseVisitor:public Visitor { public: ChineseVisitor(){} virtual ~ChineseVisitor(){} /*Interface Implement*/ virtual void visit(ChinaElement *celm) { cout<<"/nNow Chinese be visiting China's place......"<<endl; return; } virtual void visit(AmericaElement *aelm) { cout<<"/nNow Chinese be visiting America's place......"<<endl; return; } //Rtti - Implement double-dispatch virtual void visitRtti(CountryElement *elm) { if(typeid(*elm)==typeid(AmericaElement)) //注意typeid(*elm),不是typeid(elm),刚开始搞错了,真是汗...... cout<<"/nNow Chinese be visiting(Rtti) America's place......"<<endl; else if(typeid(*elm)==typeid(ChinaElement)) cout<<"/nNow Chinese be visiting(Rtti) China's place......"<<endl; return; } }; #endif  

/******************************************************************* * * DESCRIPTION:AmericanVisitor Class [American Visitor] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ #ifndef AMERICANVISITOR_H_ #define AMERICANVISITOR_H_ /** include files **/ #include <iostream> #include "Visitor.h" #include "AmericaElement.h" #include "ChinaElement.h" using namespace std; /** * AmericanVisitor Class * * @author NeeSky (2009-9-28) */ class AmericanVisitor:public Visitor { public: AmericanVisitor(){} virtual ~AmericanVisitor(){} /*Interface Implement*/ virtual void visit(ChinaElement *celm) { cout<<"/nNow American be visiting China's place......"<<endl; return; } virtual void visit(AmericaElement *aelm) { cout<<"/nNow American be visiting America's place......"<<endl; return; } //Rtti - Implement double-dispatch virtual void visitRtti(CountryElement *elm) { if(typeid(*elm)==typeid(AmericaElement)) cout<<"/nNow American be visiting(Rtti) America's place......"<<endl; else if(typeid(*elm)==typeid(ChinaElement)) cout<<"/nNow American be visiting(Rtti) China's place......"<<endl; return; } }; #endif  

/******************************************************************* * * DESCRIPTION:Visitor Pattern [访问者模式-提供支持Single-Dispatch的Multi-Dispatch策略] * * AUTHOR:Neesky * * DATE:2009-9-28 * *******************************************************************/ /** include files **/ #include <iostream> #include "Visitor.h" #include "CountryElement.h" #include "ChinaElement.h" #include "AmericaElement.h" #include "ChineseVisitor.h" #include "AmericanVisitor.h" using namespace std; /** * Main Program [Visitor Pattern 访问者模式] * * @author NeeSky (2009-9-28) * * @param argc * @param argv * * @return int */ int main (int argc, char *argv[]) { /*New Two Place of China and America*/ ChinaElement *_celm=new ChinaElement(); AmericaElement *_aelm=new AmericaElement(); /*New Two Visitor from China and America*/ Visitor *_cvis=new ChineseVisitor(); Visitor *_avis=new AmericanVisitor(); /*Now Chinese visit America Place*/ _cvis->visit(_aelm); _aelm->AcceptVisitor(_cvis); /*Now American visit China Place*/ _avis->visit(_celm); _celm->AcceptVisitor(_avis); /*RTTI Now Chinese visit America Place*/ _cvis->visitRtti(_aelm); _aelm->AcceptVisitor(_cvis); /*RTTINow American visit China Place*/ _avis->visitRtti(_celm); _celm->AcceptVisitor(_avis); return(0); }  

 

【输出】

[GoF设计模式]Composite模式和Visitor模式的C++实现_第3张图片

你可能感兴趣的:(设计模式,C++,Class,include,Constructor,destructor)