4.3Composite

意图:

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

 

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

 

生活中的例子

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


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

 

例子:

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

class Component
{
protected:
	string name;
public:
	Component(string name)
	{
		this->name = name;
	}

public:
	virtual void Add(Component *c){}
	virtual void Remove(Component *c){}
	virtual void Display(int depth){}

};

class Leaf : public Component
{
public:
	Leaf(string name) : Component(name){}
	virtual void Add(Component *c)
	{
		cout<<"Cannot add to a leaf"<<endl;
	}

	virtual void Remove(Component *c)
	{
		cout<<"Cannot add to a leaf"<<endl;
	}

	virtual void Display(int depth)
	{
		string s(depth, '-');
		cout<<s<<name<<endl;
	}
};

class Composite : public Component
{
private:
	list<Component*> children;
public:
	Composite(string name) : Component(name){}
	virtual void Add(Component *c)
	{
		children.push_back(c);
	}

	virtual void Remove(Component *c)
	{
		children.remove(c);
	}

	virtual void Display(int depth)
	{
		string s(depth, '-');
		cout<<s<<name<<endl;
		for (list<Component*>::iterator iter=children.begin();
			iter!=children.end(); ++iter)
		{
			(*iter)->Display(depth+2);
		}
	}
};
int main(int argc, char **argv)
{
	Composite *root = new Composite("root");
	root->Add(new Leaf("Leaf A"));
	root->Add(new Leaf("Leaf B"));

	Composite *comp = new Composite("Composite X");
	comp->Add(new Leaf("Leaf XA"));
	comp->Add(new Leaf("Leaf XB"));

	root->Add(comp);

	Composite *comp2 = new Composite("Composite XY");
	comp2->Add(new Leaf("Leaf XYA"));
	comp2->Add(new Leaf("Leaf XYB"));

	comp->Add(comp2);

	root->Add(new Leaf("Leaf C"));

	Leaf *leaf = new Leaf("Leaf D");
	root->Add(leaf);
	root->Remove(leaf);

	root->Display(1);

	system("pause");
	return 0;
}



大话设计模式的例子:

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


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

class Company
{
protected:
	string name;
public:
	Company(string name) : name(name){}
	virtual void Add(Company *c){}
	virtual void Remove(Company *c){}
	virtual void Display(int depth){}
	virtual void LineofDuty(){}
};

class ConcreteCompany : public Company
{
private:
	list<Company*> children;
public:
	ConcreteCompany(string name) : Company(name){}
	virtual void Add(Company *c)
	{
		children.push_back(c);
	}

	virtual void Remove(Company *c)
	{
		children.remove(c);
	}

	virtual void Display(int depth)
	{
		string s(depth, '-');
		cout<<s<<name<<endl;
		for (list<Company*>::const_iterator iter=children.begin();
			iter!=children.end(); ++iter) {
				(*iter)->Display(depth+2);
		}
	}

	virtual void LineofDuty()
	{
		for (list<Company*>::const_iterator iter=children.begin();
			iter!=children.end(); ++iter) {
				(*iter)->LineofDuty();
		}
	}
};

class HRDepartment : public Company
{
public:
	HRDepartment(string name) : Company(name){}
	virtual void Display(int depth)
	{
		string s(depth, '-');
		cout<<s<<name<<endl;
	}
	virtual void LineofDuty()
	{
		cout<<name<<" "<<"员工招聘培训管理"<<endl;
	}
};

class FinanceDepartment : public Company
{
public:
	FinanceDepartment(string name) : Company(name){}
	virtual void Display(int depth)
	{
		string s(depth, '-');
		cout<<s<<name<<endl;
	}
	virtual void LineofDuty()
	{
		cout<<name<<" "<<"公司财务收支管理"<<endl;
	}
};

int main(int argc, char **argv)
{
	ConcreteCompany *root = new ConcreteCompany("北京公司总部");
	

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

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

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

	root->Add(new HRDepartment("总公司人力资源部"));
	root->Add(compShang);
	root->Add(new FinanceDepartment("总公司财务部"));

	cout<<"结构图"<<endl;
	root->Display(1);

	cout<<"职责"<<endl;
	root->LineofDuty();

	system("pause");
	return 0;
}


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

 

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

组合模式和其他相关模式

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

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

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

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

4(观察者模式)Visitor将本来应该分布在CompositeL e a f类中的操作和行为局部化。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值