首页 > 代码库 > 组合模式之C++实现

组合模式之C++实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载!

       组合模式(Composite)也叫部分-整体模式,是一种非常实用的设计模式,当我们发现需求中系统体现的是整体与局部的层次关系,并且用户希望将组合对象单个对象一致性对待,这个时候“组合模式”的作用可以得到淋漓尽致地发挥了。

        接触过Linux的人都知道Linux的文件系统采用的一种树状的层次结构,在Linux系统中,目录和普通文件都被系统视为文件,而目录内又可以包含普通文件,这样Linux的文件系统就是以这种递归的方式定义。如果我们想描述这样的数据结构,可以考虑采用组合模式。

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

        从上面的定义我们可以得出组合模式的两大特点:

        1.从模式结构本身来看:模式本身体现的是一种整体与部分的层次结构关系;

        2.从用户的角度(客户端)分析:整体(分支结点)与部分(叶子结点)具有相同的接口,被形态上没有差别。

       组合模式的结构


       本图来自《大话设计模式》

        举例

        下图是一种组合模式的举例:


       C++实现代码(针对以上面的举例)

#include<iostream>
#include<string>
#include<list>
using namespace std;
class Component//抽象类,用户通过该接口来访问其子部件
{
protected:
	string name;
public:
	Component(){}
	Component(string str):name(str){};
	virtual void Add(Component*)=0;//增加子部件
	virtual void Remove(Component*)=0;//删除子部件
	virtual void Display(int depth)=0;//遍历结点,depth表示结点的深度
};
class Leaf:public Component
{
public:
	Leaf(string name):Component(name){}//调用基类的构造函数初始化派生类的基类部分
	void Add(Component* c)
	{
		cout<<"不能向叶子结点添加部件!"<<endl;
	}
	void Remove(Component* c)
	{
		cout<<"不能从叶子结点删除部件!"<<endl;
	}
	void Display(int depth)
	{
		cout<<string(depth,'-')<<name<<endl;
	}
};

class Composite:public Component//添加分支结点(即非叶子结点)
{
private:
	list<Component*> child;//孩子
public:
	Composite(){}//基类Component调用其默认的构造函数
	Composite(string name):Component(name){}
	void Add(Component *c)
	{
		child.push_back(c);
	}
	void Remove(Component *c)
	{
		child.remove(c);
	}
	void Display(int depth)
	{
		cout<<string(depth,'-')<<name<<endl;
		list<Component*>::iterator iter=child.begin();
		while(iter!=child.end())
		{
			(*iter)->Display(depth+1);//递归遍历
			iter++;
		}
	}
}; 
int main()
{
	Composite root("root");
	/****添加root的孩子结点pA****/
	Leaf *pA=new Leaf("Leaf A");
	root.Add(pA);

	/****添加root的孩子结点pB***/
	Leaf *pB=new Leaf("Leaf B");//添加root的孩子pB
	root.Add(pB);

	/****添加root的分支结点comp***/
	Composite *comp1=new Composite("Composite X");
	Leaf *pXA=new Leaf("Leaf XA");
	Leaf *pXB=new Leaf("Leaf XB");
	root.Add(comp1);
	
	/***添加comp1的分支结点comp2****/
	Composite *comp2=new Composite("Composite XY");
    Leaf *pXYA=new Leaf("Leaf XYA");
	Leaf *pXYB=new Leaf("Leaf XYB");
	comp2->Add(pXYA);
	comp2->Add(pXYB);
	comp1->Add(comp2);
	/***添加root的孩子结点pC和pD****/
	Leaf *pC=new Leaf("Leaf C");
	Leaf *pD=new Leaf("Leaf D");
	root.Add(pC);
	root.Add(pD);
    cout<<"显示当前树的结果:"<<endl;
	root.Display(1);
	/****删除root的孩子结点pD***/
	cout<<"显示删除结点D后的结果:"<<endl;
	root.Remove(pD);//注意,只是从树中删除了,并没有从堆中删除
	root.Display(1);

	/***释放所申请的堆内存空间,C++的麻烦就在此呀,哈哈***/
	delete pA;
	delete pB;
	delete comp1;
	delete pC;
	delete pD;
	delete pXA;
	delete pXB;
	delete comp2;
	delete pXYA;
	delete pXYB;
	return 0;
}

       测试结果

      

参考资料:

[1]《大话设计模式》

[2]《设计模式之禅》

[3]《HeadFirst设计模式》