Published on

设计模式(8)——组合 Composite

Authors
  • avatar
    Name
    Leon
    Twitter

八、Composite(组合模式,对象结构型模式)

1. 意图:

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

2. 适用:

  1. 想表示对象的部分-整体层次结构
  2. 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象

3. 类图:

4. 相关模式:

  通常部件-父部件连接用于 Responsibility of Chain 模式。   Decorator 模式经常与 Composite 模式一起使用。当装饰和组合一起使用时,它们通常有一个公共的父类。因此装饰必须支持具有 Add、Remove 和 GetChild 操作的 Component 接口。

5. C++实现:

  1. 编写一个组件抽象基类(接口) Component,含有操作函数 OperationAddRemoveGetChild
  2. 编写一个叶子(部分)类 Leaf,一个组合(整体)类 Composite,都通过继承 Component 而具有一致性的操作 Operation

Composite.h

//Composite.h
#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_

#include <vector>
using namespace::std;

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

class Component
{
public:
	virtual void Operation() = 0;
	virtual void Add(Component*);
	virtual void Remove(Component*);
	virtual Component* GetChild(int index);
	virtual ~Component();
protected:
	Component();
};

//Leaf是叶子结点,也就是不含有子组件的结点类,所以不用实现Add,Remove,GetChild等方法
class Leaf : public Component
{
public:
	//只实现Operation接口
	virtual void Operation();
	Leaf();
	~Leaf();
};

//Composite含有子组件的类
class Composite : public Component
{
public:
	Composite();
	~Composite();
	//实现所有接口
	void Operation();
	void Add(Component*);
	void Remove(Component*);
	Component* GetChild(_Uint32t index);
private:
	//这里采用vector来保存子组件
	vector<Component*> m_ComVec;
};

#endif

Composite.cpp

//Composite.cpp
#include "Composite.h"
#include <iostream>
#include <algorithm>

using namespace::std;

Component::Component(){}

Component::~Component(){}

void Component::Add(Component* com)
{
	cout << "add" << endl;
}

void Component::Remove(Component* com)
{
	//..
}

void Component::Operation()
{
	//..
	cout << "Component::Operation" << endl;
}

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

Leaf::Leaf(){}
Leaf::~Leaf(){}

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

Composite::Composite(){}
Composite::~Composite(){}

void Composite::Add(Component* com)
{
	this->m_ComVec.push_back(com);
}

void Composite::Remove(Component* com)
{
	vector<Component*>::iterator iter;
	iter = std::find(this->m_ComVec.begin(), m_ComVec.end(), com);
	while (m_ComVec.end() != iter)
	{
		m_ComVec.erase(iter);
		iter = std::find(m_ComVec.begin(), m_ComVec.end(), com);
	}
}

void Composite::Operation()
{
	cout << "Composite::Operation" << endl;
	vector<Component*>::iterator iter = this->m_ComVec.begin();
	for(; iter != this->m_ComVec.end(); iter++)
	{
		(*iter)->Operation();//递归
	}
}

Component* Composite::GetChild(_Uint32t index)
{
	if(index < 0 || index > this->m_ComVec.size())
	{
		return NULL;
	}
	return this->m_ComVec[index];
}

main.cpp

//main.cpp
#include "Composite.h"
#include <iostream>
using namespace::std;

int main()
{
	Leaf* pLeaf1 = new Leaf();
	Leaf* pLeaf2 = new Leaf();

	//叶子与组合对象都继承了相同的接口,所以语法上是对的,但
	//叶子Add,Remove,GetChild函数没有重新定义,都继承自基类,
	//没有实际意义。
	pLeaf1->Add(pLeaf2);
	pLeaf1->Remove(pLeaf2);

	//叶子结点实现了Opeeration()方法,
	pLeaf1->Operation();

	//组合对象实现了基类的所有接口,所以可以做各种操作(Add,Remove
	//GetChild,Operation)。
	Composite* pCom = new Composite();
	//组合对象添加叶子结点
	pCom->Add(pLeaf1);
	pCom->Add(pLeaf2);
	pCom->Operation();

	Composite* pRoot = new Composite();
	pRoot->Add(new Leaf());
	//组合对象添加组合对象
	pRoot->Add(pCom);
	pRoot->Operation();
	cin.get();

	return 0;
}