您的位置:首页 > 其它

设计模式之组合模式(composite)

2013-06-16 00:03 316 查看





概述

组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

生活中的例子

组合模式将对象组合成树形结构以表示"部分-整体"的层次结构。让用户一致地使用单个对象和组合对象。虽然例子抽象一些,但是算术表 达式确实是组合的例子。算术表达式包括操作数、操作符和另一个操作数。操作数可以是数字,也可以是另一个表达式。这样,2+3和(2+3)+(4*6)都 是合法的表达式。(来自http://blog.163.com/renjianqin_1984/blog/static/1328821542010720104922316/)

在上面的图中,Component是组合和个体的基类,单个对象成了Leaf,而组合对象就是Composite,他们同时具有父类的操作。因此在客户看来他们是一致的。这样的话我们可以在Composite下再可以添加Composite对象或者Leaf对象,如此递归成了树形结构。

再来个例子(来自大话设计模式)



/*

    有一家公司,总公司在北京,在上海有其在华东地区的分公司,然后在南京和杭州分别有各自的办事处。这里每个地方无论是总部还是分部都会有相同的部门设置,所以可以用Composite模式解决。

/*

#include<iostream>
#include<string>
#include<vector>
using namespace std;

class Company
{
protected:
string cname;
public:
Company(string name):cname(name)
{
}
virtual void Add(Company *c)=0;//增加
virtual void Remove(Company *c)=0;//删除
virtual void Display(int depth)=0;//显示
virtual void LineOfDuty()=0;//职责
};

//具体公司
class ConcreteCompany:public Company
{
private:
vector<Company*> children;
public:
ConcreteCompany(string name):Company(name)
{
}
void Add(Company *c)
{
children.push_back(c);
}
void Remove(Company *c)
{
children.erase(&c);
}
void Display(int depth)
{
string s(depth,'-');
cout<<s<<cname<<endl;
vector<Company*>::iterator iter;
for(iter=children.begin();iter!=children.end();iter++)
{
(*iter)->Display(depth+2);
}
}
void LineOfDuty()
{
vector<Company*>::iterator iter;
for(iter=children.begin();iter!=children.end();++iter)
{
(*iter)->LineOfDuty();
}
}
};

//人事部
class HRDepartment:public Company
{
private:
vector<Company*> children;
public:
HRDepartment(string name):Company(name)
{
}
void Add(Company *c)
{
children.push_back(c);
}
void Remove(Company *c)
{
children.erase(&c);
}
void Display(int depth)
{
string s(depth,'-');
cout<<s<<cname<<endl;
}
void LineOfDuty()
{
cout<<cname<<"\t员工招聘培训管理"<<endl;
}
};

//财务部
class FinanceDepartment:public Company
{
private:
vector<Company*> children;
public:
FinanceDepartment(string name):Company(name)
{
}
void Add(Company *c)
{
children.push_back(c);
}
void Remove(Company *c)
{
children.erase(&c);
}
void Display(int depth)
{
string s(depth,'-');
cout<<s<<cname<<endl;
}
void LineOfDuty()
{
cout<<cname<<"\t公司财务收支管理"<<endl;
}
};

int main()
{
ConcreteCompany *c=new ConcreteCompany("北京总公司");
c->Add(new HRDepartment("总公司人力资源部"));
c->Add(new FinanceDepartment("总公司财务管理部"));

ConcreteCompany *c1=new ConcreteCompany("上海华东分公司");
c1->Add(new HRDepartment("华东分公司人力资源部"));
c1->Add(new FinanceDepartment("华东分公司财务部"));
c->Add(c1);

ConcreteCompany *c2=new ConcreteCompany("南京办事处");
c1->Add(c2);
c2->Add(new HRDepartment("南京办事处人力资源部"));
c2->Add(new FinanceDepartment("南京办事处财务部"));

ConcreteCompany *c3=new ConcreteCompany("杭州办事处");
c1->Add(c3);
c3->Add(new HRDepartment("杭州办事处人力资源部"));
c3->Add(new FinanceDepartment("杭州办事处财务部"));

cout<<"结构图:"<<endl;
c->Display(1);
cout<<endl;
cout<<"职责:"<<endl;
c->LineOfDuty();

return 0;

}


运行结果:



这就是一个树形结构,子节点都可以跟父节点一样拥有相同的职能,但是他们所处的层次却是清晰地分开了,这就是Composite模式的好处。

注:组合模式一种继承关系,派生类中含有包含基类指针的容器。

组合模式和其他相关模式

1)装饰模式(Decorator模式)经常与Composite模式一起使用。当装饰和组合一起使用时,它们

通常有一个公共的父类。因此装饰必须支持具有 Add、Remove和GetChild 操作的Component接口。

2)Flyweight模式让你共享组件,但不再能引用他们的父部件。

3)(迭代器模式)Itertor可用来遍历Composite。

4)(观察者模式)Visitor将本来应该分布在Composite和L e a f类中的操作和行为局部化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: