设计模式组合模式

组合模式Composite):

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


组合模式代码

#pragma once
#include <set>
#include <string>
#include <iostream>
using namespace std;

//Component为组合中的对象声明接口,在适当情况下,实现所有类接口的默认行为。
//声明一个接口用于访问和管理Component的子部件。
class CComponent
{
protected:
    string m_pstrName;
public:
	CComponent(const string &strName)
	{
		m_pstrName = strName;
	}
	virtual void Add(CComponent  *const pc) = 0;
	virtual void Remove(CComponent  *const pc) = 0;
	virtual void Display(const int &nDepth) = 0;
};

//Leaf 在组合中表示叶节点对象,叶节点没有子节点。
class CLeaf : public CComponent
{
public:
	CLeaf(const string &strName) : CComponent(strName){}
    void Add(CComponent  *const pc)
	{
		cout<<"Cannot add to a leaf"<<endl;
	}
	void Remove(CComponent  *const pc)
	{
		cout<<"Cannot remove from a leaf"<<endl;
	}
	void Display(const int &nDepth)
	{
		cout<<'-'<<nDepth<<':'<<m_pstrName<<endl;
	}
};

//Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与
//子部件有关的操作,比如增加Add和阐述Remove。
class CComposite : public CComponent
{
private:
	set<CComponent*> m_Children;
public:
	CComposite(const string &strName) : CComponent(strName) 
	{
		m_Children.clear();
	}
	void Add(CComponent * const pC)
	{
		m_Children.insert(pC);
	}
	void Remove(CComponent * const pC)
	{
		m_Children.erase(pC);
		delete pC;
	}
	void Display(const int &nDepth)
	{
		cout<<'-'<<nDepth<<':'<<m_pstrName<<endl;
		for each(auto i in m_Children)
		{
			i->Display(nDepth + 1);
		}
	}
	~CComposite()
	{
		for each(auto i in m_Children)
		{
			delete i;
		}
	}
};
客户端调用

#include "stdafx.h"
#include "CompositeMode.h"
#include <windows.h>
using namespace std;

int main()
{
	CComposite *pRoot = new CComposite("root");
	pRoot->Add(new CLeaf("Leaf A"));
	pRoot->Add(new CLeaf("Leaf B"));

	CComposite *pComp = new CComposite("Composite X");
	pComp->Add(new CLeaf("Leaf XA"));
	pComp->Add(new CLeaf("Leaf XB"));

	pRoot->Add(pComp);

	pRoot->Display(1);
	delete pRoot;
	return 0;
}
运行结果

透明方式与安全方式
    透明方式,也就是说在Component中声明所有用来管理子对象的方法,其中包括Add/Remove等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add和Remove方法的功能,所以实现它是没有意义的。所以Leaf类中不用Add和Remove方法也是可以的,这样就叫做安全方式,也就是在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的接口方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做响应的判断,带来了不便。
何时使用组合模式?
    需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。
组合模式的好处
    组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不对地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
    用户是不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些判断语句了,简单的说就是组合模式让客户可以一致地使用组合结构和单个对象。
原文地址:https://www.cnblogs.com/csnd/p/12062334.html