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

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

UML图如下:


在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等,这样实现Component接口的所有子类都具备了Add和Remove。
这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备 完全一致的行为 接口。
但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的 功能,所以实现它是没有意义的。

何时使用组合模式
当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。

用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合二写一些选择判断语句了。

组合模式让客户可以一致地使用组合结构和单个对象。

抽象基类:
1)Component:为组合中的对象声明接口,声明了类共有接口的缺省行为(如这里的Add,Remove,GetChild函数),声明一个接口函数可以访问Component的子组件.

接口函数:
1)Component::Operatation:定义了各个组件共有的行为接口,由各个组件的具体实现.
2)Component::Add添加一个子组件
3)Component::Remove::删除一个子组件.
4)Component::GetChild:获得子组件的指针.

说明:
Component模式是为解决组件之间的递归组合提供了解决的办法,它主要分为两个派生类:

1)、Leaf是叶子结点,也就是不含有子组件的结点

2)、Composite是含有子组件的类.

举一个例子来说明这个模式,在UI的设计中,最基本的控件是诸如Button、Edit这样的控件,相当于是这里的Leaf组件,而比较复杂的控件比如Panel则可也看做是由这些基本的组件组合起来的控件,相当于这里的Composite,它们之间有一些行为含义是相同的,比如在控件上作一个点击,移动操作等等的,这些都可以定义为抽象基类中的接口虚函数,由各个派生类去实现之,这些都会有的行为就是这里的Operation函数,而添加、删除等进行组件组合的操作只有非叶子结点才可能有,所以虚拟基类中只是提供接口而且默认的实现是什么都不做


附上代码实例:

#include"stdafx.h"

#include<iostream>

using namespace std;

#include<vector>


class  Component
{
public:
	
	virtual ~ Component()
	{
	
	}
	virtual void Operation() = 0;

	virtual void Add(Component *pCom)
	{
		cout<<"Component::Add"<<endl;

	}

	virtual void Remove(Component *pCom)
	{
		cout<<"Componet::Remove"<<endl;
	}

	virtual Component *GetChild(int index)
	{
		return NULL;	
	}

protected:
	 Component()
	 {

	 }
private:

};

//
//void Component::Operation()
//{
//
//
//}

class Leaf : public Component
{
public :

	void Operation()
	{
		cout<<"Leaf Operation" <<endl;
	}

	Leaf()
	{
	
	}

	~Leaf()
	{
	
	}
};

class Compostite : public Component
{
public:
	Compostite()
	{
	
	}
	~Compostite()
	{
	
	}
	
	void Operation()
	{
		vector<Component *>::iterator it = m_Comvec.begin();
		for(; it!= m_Comvec.end();it++)
		{
			(*it)->Operation();
		}
		
	}

	void Add(Component *pCom)
	{
		m_Comvec.push_back(pCom);
	}

	void Remove(Component *pCom)
	{
		vector<Component *>::iterator it = m_Comvec.begin();
		for(;it!=m_Comvec.end();it++)
		{
			if((*it) == pCom)
			{
				m_Comvec.erase(it);
			}
		}
		//m_Comvec.erase(it);
	}

	Component *GetChild(int index)
	{
		if(index < 0|| index > m_Comvec.size())
		{
			return NULL;
		}


		return m_Comvec[index];


			
	}
private:
	vector<Component *> m_Comvec;

};


client:

// CompositeMode.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include"Composite.hpp"
#include"Company.hpp"
int _tmain(int argc, _TCHAR* argv[])
{
	
/***************** Copmosit Client ********************/	
	Component *pRoot = new Compostite();

	pRoot->Add(new Leaf());
	pRoot->Operation();
	cout<<endl;
	Leaf *pLeaf1 =  new Leaf();
	Leaf *pLeaf2 =  new Leaf();

	Compostite *pCom =  new Compostite();

	pCom->Add(pLeaf1);
	pCom->Add(pLeaf2);

	pCom->Operation();
	cout<<endl;

	pRoot->Add(pCom);

	pRoot->Operation();




	system("pause");
	return 0;
}

另一个实例的UML 图



#pragma once

#include"stdafx.h"
#include<iostream>
#include<string>
#include<list>
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  FinaceDepartment:public Company
{
public:
	FinaceDepartment(string name):Company(name)
	 {
	 
	 }
	~ FinaceDepartment()
	{
	
	}

	void Show(int depth)
	{
		for(int i = 0;i<depth ;i++)
		{
			cout<<"-";
		
		}
			cout<<m_name<<endl;
	}

private:

};


class HrDepartment : public Company
{
public:
	HrDepartment(string  name):Company(name)
	{
	
	};
	~HrDepartment()
	{
	
	}

	void Show(int depth)
	{
		for(int i = 0;i<depth ;i++)
		{
			cout<<"-";
			
		}
		cout<<m_name<<endl;
	}
private:
};


class ConcreteCompany : public Company
{

public:
	ConcreteCompany(string name):Company(name)
	{
	
	}
	~ConcreteCompany()
	{
	
	}

	void  Add(Company *pCom)
	{
		m_listCom.push_back(pCom);
	}

	void Show(int depth)
	{
		for(int i = 0;i<depth ;i++)
		{
			cout<<"-";
			
		}
		cout<<m_name<<endl;

		list<Company *>::iterator  it = m_listCom.begin();

		for(;it != m_listCom.end();it ++)
		{
			(*it)->Show(depth +2);	
		}
	
	}
private:
	list<Company *> m_listCom;

};


// CompositeMode.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include"Composite.hpp"
#include"Company.hpp"
int _tmain(int argc, _TCHAR* argv[])
{
	

/************************ Company Client ******************/
	

	//总部
	Company *root =  new ConcreteCompany("总部");
	Company *leaf1 =new FinaceDepartment("财务部");
	Company *leaf2 = new HrDepartment("人力资源部");

	root->Add(leaf1);
	root->Add(leaf2);
	
	//分公司A
	 Company *mid1  = new ConcreteCompany("分公司A");
     Company *leaf3 =new FinaceDepartment("财务部");
     Company *leaf4 =new HrDepartment("人力资源部");
     mid1->Add(leaf3);
     mid1->Add(leaf4);
     root->Add(mid1);

	  //分公司B
     Company          *mid2	   = new ConcreteCompany("分公司B");
     FinaceDepartment  *leaf5    =new FinaceDepartment("财务部");
     HrDepartment     *leaf6     =new HrDepartment("人力资源部");
     mid2->Add(leaf5);
     mid2->Add(leaf6);
     root->Add(mid2);


     root->Show(0);
	 mid2->Show(1);

	//root->Show(1);


	system("pause");
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值