设计模式之 - 组合模式

一、定义

        将对象组合成树形结构以表示“部分-整体”的层次结构。组合使得用户对单个对象和组合对象的使用具有一致性。注意两个字“树形”。这种树形结构在现实生活中随处可见,比如一个集团公司,它有一个母公司,下设很多家子公司。不管是母公司还是子公司,都有各自直属的财务部、人力资源部、销售部等。对于母公司来说,不论是子公司,还是直属的财务部、人力资源部,都是它的部门。整个公司的部门拓扑图就是一个树形结构。

二、组成

1) 抽象构件角色(Component):它为组合中的对象声明接口,也可以为共有接口实现缺省行为。
2) 树叶构件角色(Leaf):在组合中表示叶节点对象——没有子节点,实现抽象构件角色声明的接口。

3) 树枝构件角色(Composite):在组合中表示分支节点对象——有子节点,实现抽象构件角色声明的接口;存储子部件。

三、实现

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

// 抽象的部件类描述将来所有部件共有的行为
class Component
{
public:
	Component(string name) : m_strCompname(name){}
	virtual ~Component(){}
	virtual void Operation() = 0;
	virtual void Add(Component *) = 0;
	virtual void Remove(Component *) = 0;
	virtual Component *GetChild(int) = 0;
	virtual string GetName()
	{
		return m_strCompname;
	}
	virtual void Print() = 0;
protected:
	string m_strCompname;
};

//树叶构建
class Leaf : public Component
{
public:
	Leaf(string name) : Component(name)	{}
	void Operation()
	{
		cout<<"I'm "<<m_strCompname<<endl;
	}
	void Add(Component *pComponent){}
	void Remove(Component *pComponent){}
	Component *GetChild(int index)
	{
		return NULL;
	}
	void Print(){}
};

//树枝构建
class Composite : public Component
{
public:
	Composite(string name) : Component(name){}
	~Composite()
	{
		vector<Component *>::iterator it = m_vecComp.begin();
		while (it != m_vecComp.end())
		{
			if (*it != NULL)
			{
				cout<<"----delete "<<(*it)->GetName()<<"----"<<endl;
				delete *it;
				*it = NULL;
			}
			m_vecComp.erase(it);
			it = m_vecComp.begin();
		}
	}
	void Operation()
	{
		cout<<"I'm "<<m_strCompname<<endl;
	}
	void Add(Component *pComponent)
	{
		m_vecComp.push_back(pComponent);
	}
	void Remove(Component *pComponent)
	{
		for (vector<Component *>::iterator it = m_vecComp.begin(); it != m_vecComp.end(); ++it)
		{
			if ((*it)->GetName() == pComponent->GetName())
			{
				if (*it != NULL)
				{
					delete *it;
					*it = NULL;
				}
				m_vecComp.erase(it);
				break;
			}
		}
	}
	Component *GetChild(int index)
	{
		if (index > m_vecComp.size())
		{
			return NULL;
		}
		return m_vecComp[index - 1];
	}
	void Print()
	{
		for (vector<Component *>::iterator it = m_vecComp.begin(); it != m_vecComp.end(); ++it)
		{
			cout<<(*it)->GetName()<<endl;
		}
	}
private:
	vector<Component *> m_vecComp;
};
int main(int argc, char *argv[])
{
	Component *pNode = new Composite("Beijing Head Office");
	Component *pNodeHr = new Leaf("Beijing Human Resources Department");
	Component *pSubNodeSh = new Composite("Shanghai Branch");
	Component *pSubNodeCd = new Composite("Chengdu Branch");
	Component *pSubNodeBt = new Composite("Baotou Branch");
	pNode->Add(pNodeHr);
	pNode->Add(pSubNodeSh);
	pNode->Add(pSubNodeCd);
	pNode->Add(pSubNodeBt);
	pNode->Print();
	Component *pSubNodeShHr = new Leaf("Shanghai Human Resources Department");
	Component *pSubNodeShCg = new Leaf("Shanghai Purchasing Department");
	Component *pSubNodeShXs = new Leaf("Shanghai Sales department");
	Component *pSubNodeShZb = new Leaf("Shanghai Quality supervision Department");
	pSubNodeSh->Add(pSubNodeShHr);
	pSubNodeSh->Add(pSubNodeShCg);
	pSubNodeSh->Add(pSubNodeShXs);
	pSubNodeSh->Add(pSubNodeShZb);
	pNode->Print();
	// 公司不景气,需要关闭上海质量监督部门
	pSubNodeSh->Remove(pSubNodeShZb);
	if (pNode != NULL)
	{
		delete pNode;
		pNode = NULL;
	}
	return 0;
}

四、优缺点

       从上面的举例中可以看到,组合模式有以下优点:
1) 使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2) 更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利!
当然组合模式也少不了缺点:组合模式不容易限制组合中的构件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值