组合模式(Composite)应用背景
在绘图编辑器的应用程序中,用户可以使用简单图形组件创建复杂的图表,也可以组合多个简单图形形成较大的组件,这些新产生图形组件又可以组合成为更大的组件,如此产生不断递归层次。类似情况也有在文件系统中,一个目录中可以包含单个独立文件和子文件夹,子文件夹中又可以包含单个独立文件和子文件夹等等。 软件设计中,针对这种“部分–整体”的层次结构,提出了组合模式描述。
组合模式将对象组合成树形结构以表示“部分–整体”的层次结构,组合对象与基本对象拥有相同的接口,用户对单个对象和组合对象的使用具有一致性,不必关心到底是处理一个单个对象还是处理一个组合对象。简单可以理解为:是把一些现有的对象或者元素,经过组合后组成新的对象,新的对象提供内部方法,可以很方便的完成这些元素或者内部对象的访问和操作,也可以把组合对象理解成一个容器,容器提供各种访问其内部对象或者元素的API,用户只需要使用这些方法即可。
组合模式(Composite)UML图
组合模式(Composite)代码示例
class Component
{
public:
Component(std::string name):m_strName(name){};
virtual ~Component(){};
public:
virtual void Operation() = 0;
virtual void Add(Component* pObj) = 0;
virtual void Remove(Component* pObj) = 0;
virtual Component* GetChild(int index) = 0;
virtual std::string GetName()
{
return m_strName;
}
protected:
std::string m_strName;
};
class Leaf: public Component
{
public:
Leaf(std::string name): Component(name){ }
~Leaf(){}
public:
void Operation()
{
//TODO:
}
void Add(Component* pObj)
{
//leaf, no need realization
};
void Remove(Component* pObj)
{
//leaf, no need realization
};
Component* GetChild(int index)
{
return NULL; //leaf, no need realization
};
};
class Composite: public Component
{
public:
Composite(std::string name):Component(name){}
~Composite()
{
std::vector<Component *>::iterator itor = m_vecComponent.begin();
while (itor != m_vecComponent.end())
{
if (*itor != NULL)
{
delete *itor;
*itor = NULL;
}
m_vecComponent.erase(itor);
itor = m_vecComponent.begin();
}
}
private:
std::vector<Component*> m_vecComponent;
public:
void Operation()
{
//TODO:
}
void Add(Component* pObj)
{
m_vecComponent.push_back(pObj);
}
void Remove(Component* pObj)
{
std::vector<Component*>::iterator itor=m_vecComponent.begin();
for( ; itor!=m_vecComponent.end(); ++itor)
{
if((*itor)->GetName() == pObj->GetName())
{
if (*itor != NULL)
{
delete *itor;
*itor = NULL;
}
m_vecComponent.erase(itor);
break;
}
}
}
Component* GetChild(int index)
{
if(index > m_vecComponent.size())
return NULL;
return m_vecComponent[index-1];
}
};
//Client usage example:
Component *pRootNode = new Composite("Head Office");
Component *pNodeHR = new Leaf("Head Office HR");
Component *pSubNodeSH = new Composite("SH Office");
Component *pSubNodeXA = new Composite("XA Office");
Component *pSubNodeHK = new Composite("HK Office");
pRootNode->Add(pNodeHR);
pRootNode->Add(pSubNodeSH);
pRootNode->Add(pSubNodeXA);
pRootNode->Add(pSubNodeHK);
pRootNode->Operation();
Component *pSubNodeSHHR = new Leaf("Shanghai HR Office");
Component *pSubNodeSHSS = new Leaf("Shanghai Sales Office");
Component *pSubNodeSHRD = new Leaf("Shanghai RD Office");
pSubNodeSH->Add(pSubNodeSHHR);
pSubNodeSH->Add(pSubNodeSHSS);
pSubNodeSH->Add(pSubNodeSHRD);
pRootNode->Operation();
pSubNodeSH->Remove(pSubNodeSHRD);
if (pSubNodeSHRD != NULL)
{
delete pSubNodeSHRD;
pSubNodeSHRD = NULL;
}
注意事项:
使用中需要特别注意内存的释放,由于组合模式中存在树形结构,当父节点都被销毁时,所有的子节点也必须被销毁,因此,代码示例使用在析构函数中对维护的Component列表进行统一销毁,这样就可以免去使用者频繁销毁子节点的麻烦。