简介
组合模式是用在树状结构中,表示部分和整体的层次结构,组合模式使客户端同等对待对象(叶子节点)和对象的组合(容器)。也分为透明组合模式和安全组合模式,透明组合模式实现了父类的所有方法,安全组合模式不实现管理叶子节点的接口。本文只记录透明组合模式。
UML 类图
示例
树状结构在我们软件设计中很常见。例如菜单下面常常会有子菜单。在此我们构造一个使用文件菜单的示例。我们使用 vector 来作为叶子节点的容器。
抽象对象,叶子节点和容器,composite.h
#ifndef COMPOSITE_H
#define COMPOSITE_H
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define SAFE_DELETE(p) if(p){delete p; p = NULL;}
class CMenu
{
public:
CMenu(string strName):m_strName(strName){}
virtual void Add(CMenu* pMenu) = 0;
virtual void Remove(CMenu* pMenu) = 0;
virtual CMenu* GetChild(int nIndex) = 0;
virtual void ShowMenuName(int indent) = 0;
public:
string m_strName;
};
class CLeafMenu:public CMenu
{
public:
CLeafMenu(string strName):CMenu(strName){}
void Add(CMenu* pMenu)
{cout<<"Leaf can not add."<<endl;}
void Remove(CMenu* pMenu)
{cout<<"Leaf can not remove."<<endl;}
CMenu* GetChild(int nIndex)
{
cout<<"Leaf has no child."<<endl;
return NULL;
}
void ShowMenuName(int indent)
{string str(indent, '-');
cout<<str<<m_strName<<endl;
}
};
class CCompositeMenu:public CMenu
{
public:
CCompositeMenu(string strName):CMenu(strName){}
void Add(CMenu* pMenu)
{m_pMenuVec.push_back(pMenu);
}
void Remove(CMenu* pMenu)
{for(vector<CMenu*>::iterator iter = m_pMenuVec.begin(); iter != m_pMenuVec.end(); ++ iter)
{if(*iter == pMenu)
{m_pMenuVec.erase(iter);
SAFE_DELETE(pMenu);
break;
}
}
}
CMenu* GetChild(int nIndex)
{return m_pMenuVec[nIndex];
}
void ShowMenuName(int indent)
{string str(indent, '-');
cout<<str<<"+"<<m_strName<<endl;
for(vector<CMenu*>::iterator iter = m_pMenuVec.begin(); iter != m_pMenuVec.end(); ++ iter)
{(*iter)->ShowMenuName(indent + 1);
}
}
public:
vector<CMenu*> m_pMenuVec;
};
#endif
客户端调用,main.cpp
#include "composite.h"
#define SAFE_DELETE(p) if(p){delete p; p = NULL;}
int main(int argc, char* argv[])
{CMenu* pRootMenu = new CCompositeMenu("File");
CMenu* pNew = new CCompositeMenu("New");
CMenu* PNewProject = new CLeafMenu("Project");
CMenu* pNewSolution = new CLeafMenu("Solution");
CMenu* pClose = new CLeafMenu("Close");
pRootMenu->Add(pNew);
pNew->Add(PNewProject);
pNew->Add(pNewSolution);
pRootMenu->Add(pClose);
pRootMenu->ShowMenuName(1);
SAFE_DELETE(pClose);
SAFE_DELETE(pNewSolution);
SAFE_DELETE(PNewProject);
SAFE_DELETE(pNew);
SAFE_DELETE(pRootMenu);
return 0;
}
输出结果:
-+File
--+New
---Project
---Solution
--Close