组合模式
组合模式,是为了解决整体和部分的一致对待的问题而产生的,要求这个整体与部分有一致的操作或行为。部分和整体都继承与一个公共的抽象类,这样,外部使用它们时是一致的,不用管是整体还是部分,使用一个方法即可遍历整体中的所有的部分。就像一个树形结构一样。
适用性:
常用于组织结构,产品结构之类的整体和部分的结构。例如图形由很多直线构成,直线由点构成,这就是整体和部分的关系。如果采用组合模式,只需要使用一个draw方法即可按遍历的方式画出所有的点,最终呈现出来的就是图形。
优点:
隐藏了整体和部分,让外部依赖于抽象,简化了代码。
缺点:
1.要求必须有一致的行为。
2.处于同一个Composite的Leaf与Leaf之间难以传递数据。
代码实现1
比如一个集团公司,它有一个母公司,下设很多家子公司。不管是母公司还是子公司,都有各自直属的财务部、人力资源部、销售部等。对于母公司来说,不论是子公司,还是直属的财务部、人力资源部,都是它的部门。整个公司的部门拓扑图就是一个树形结构。
#include <iostream> #include <list> #include <string> using namespace std; class Company { public: Company(string name) { m_name = name; } virtual ~Company(){} virtual void Add(Company *pCom){} virtual void Show(int depth) {} protected: string m_name; }; //具体公司 class ConcreteCompany : public Company { public: ConcreteCompany(string name): Company(name) {} virtual ~ConcreteCompany() {} void Add(Company *pCom) { m_listCompany.push_back(pCom); } //位于树的中间,可以增加子树 void Show(int depth) { for(int i = 0;i < depth; i++) cout<<"-"; cout<<m_name<<endl; list<Company *>::iterator iter=m_listCompany.begin(); for(; iter != m_listCompany.end(); iter++) //显示下层结点 (*iter)->Show(depth + 2); } private: list<Company *> m_listCompany; }; //具体的部门,财务部 class FinanceDepartment : public Company { public: FinanceDepartment(string name):Company(name){} virtual ~FinanceDepartment() {} virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点 { for(int i = 0; i < depth; i++) cout<<"-"; cout<<m_name<<endl; } }; //具体的部门,人力资源部 class HRDepartment :public Company { public: HRDepartment(string name):Company(name){} virtual ~HRDepartment() {} virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点 { for(int i = 0; i < depth; i++) cout<<"-"; cout<<m_name<<endl; } }; int main() { Company *root = new ConcreteCompany("总公司"); Company *leaf1=new FinanceDepartment("财务部"); Company *leaf2=new HRDepartment("人力资源部"); root->Add(leaf1); root->Add(leaf2); //分公司A Company *mid1 = new ConcreteCompany("分公司A"); Company *leaf3=new FinanceDepartment("财务部"); Company *leaf4=new HRDepartment("人力资源部"); mid1->Add(leaf3); mid1->Add(leaf4); root->Add(mid1); //分公司B Company *mid2=new ConcreteCompany("分公司B"); FinanceDepartment *leaf5=new FinanceDepartment("财务部"); HRDepartment *leaf6=new HRDepartment("人力资源部"); mid2->Add(leaf5); mid2->Add(leaf6); root->Add(mid2); root->Show(0); delete leaf1; delete leaf2; delete leaf3; delete leaf4; delete leaf5; delete leaf6; delete mid1; delete mid2; delete root; return 0; }
结果:
总公司 --财务部 --人力资源部 --分公司A ----财务部 ----人力资源部 --分公司B ----财务部 ----人力资源部 请按任意键继续. . .
上面的实现方式有缺点,就是内存的释放不好,需要客户自己动手,非常不方便。有待改进,比较好的做法是让ConcreteCompany类来释放。因为所有的指针都是存在ConcreteCompany类的链表中。C++的麻烦,没有垃圾回收机制。
代码实现2
下面示例有两种情况,add函数对于Leaf来说是没有必要的,所以可以在Leaf的add实现中什么都不写。还一种办法就是将add方法挪到Composite中,让外部使用Composite和Component。但这样的缺点就是暴露了Composite,客户端必须知道Composite才能完成操作,好处Leaf不用产生多余的方法了。
#include <iostream> #include <vector> using namespace std; class Component { public: Component(){}; virtual ~Component(){}; virtual void operation() = 0; }; class Leaf: public Component { public: Leaf(){}; ~Leaf(){}; void operation() { cout << "Operation leaf" << endl; } }; class Composite: public Component { public: Composite(){}; ~Composite(){}; void add(Component* c) { m_leafs.push_back(c); } void operation() { cout << "Operation Composite" << endl; vector<Component*>::iterator comIter = m_leafs.begin(); for (; comIter != m_leafs.end(); comIter++) { (*comIter)->operation(); } } private: vector<Component*> m_leafs; }; int main() { Component* leaf1 = new Leaf(); Component* leaf2 = new Leaf(); Composite* composite1 = new Composite(); composite1->add(leaf1); composite1->add(leaf2); Composite* composite2 = new Composite(); composite2->add(composite1); composite2->operation(); return 0; }
结果:
Operation Composite
Operation Composite
Operation leaf
Operation leaf
请按任意键继续. . .
参考 : http://blog.csdn.net/wuzhekai1985/article/details/6667564