1. 意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
2. 三种角色
抽象组件(Component)、组合式节点(Composite)、叶节点(Leaf)
3. 优点
3.1 定义了包含基本对象和组合对象的类层次结构。
客户代码中,用到基本对象的地方都可以使用组合对象。
3.2 简化客户代码,不需要关心是叶节点还是组合。
3.3 使得更容易增加新类型的组件
3.4 使设计变得更加一般化
4. 缺点
4.1 只能在运行时刻进行类型检查
5. 相关模式
5.1 通常“部件-父部件”连接用于Responsibility of Chain模式
5.2 装饰模式经常与Composite模式一起使用,通常有个公共的父类。
5.3 Flyweight让你共享组件,但不能引用它们的父部件。
5.4 Iterator可用来遍历Composite
5.5 Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。
6. 代码示意(C++)
#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Component
{
protected:
string m_strName;
public:
Component(const string &strName)
{
m_strName = strName;
}
virtual void Operation(int depth) = 0;
virtual bool Add(Component* pComponent) = 0;
virtual bool Remove(Component* pComponent) = 0;
virtual Component* GetChild(int pos) = 0;
public:
string GetName() { return m_strName; }
protected:
string GetPreLine(int depth)
{
string preLine = "";
for (int i = 0; i < depth; ++i)
{
preLine += "--";
}
return preLine;
}
};
class Leaf : public Component
{
public:
Leaf(const string& strName) :Component(strName)
{
}
virtual bool Add(Component* pComponent) {
cout << "Leaf can't add" << endl;
return false;
}
virtual bool Remove(Component* pComponent) {
cout << "Leaf can't remove" << endl;
return false;
}
virtual Component* GetChild(int pos) {
cout << "Leaf has no child" << endl;
return 0;
}
virtual void Operation(int depth) {
cout << GetPreLine(depth) << m_strName << endl;
}
};
class Composite :public Component
{
private:
vector<Component*> m_vecChildren;
public:
Composite(const string& strName) :Component(strName) {
m_strName = strName;
}
~Composite()
{
auto it = m_vecChildren.begin();
while (it != m_vecChildren.end()) {
delete* it;
it++;
}
m_vecChildren.clear();
}
virtual bool Add(Component* pComponent) {
if (pComponent == 0) {
return false;
}
m_vecChildren.emplace_back(pComponent);
//cout << "children size:" <<m_vecChildren.size()<< endl;
return true;
}
virtual bool Remove(Component* pComponent) {
if (pComponent == 0) {
return false;
}
m_vecChildren.erase(std::remove_if(m_vecChildren.begin(), m_vecChildren.end(), [&](Component *p) { return p->GetName().compare(pComponent->GetName()) == 0; }), m_vecChildren.end());
//cout << "children size:" << m_vecChildren.size() << endl;
//cout << "children capacity:" << m_vecChildren.capacity() << endl;
return true;
}
virtual Component* GetChild(int pos) {
if (pos >= 0 && pos < m_vecChildren.size()) {
return m_vecChildren[pos];
}
return 0;
}
virtual void Operation(int depth) {
cout << GetPreLine(depth) << m_strName << endl;
auto it = m_vecChildren.begin();
while (it != m_vecChildren.end()) {
(*it)->Operation(depth+1);
it++;
}
}
};
#include "Component.h"
int main() {
Composite* pRoot= new Composite("Root");
pRoot->Add(new Leaf("Leaf1"));
pRoot->Add(new Leaf("Leaf2"));
Composite* pComposite = new Composite("Composite");
pComposite->Add(new Leaf("Leaf3"));
pRoot->Add(pComposite);
pRoot->Operation(0);
cout << "------------------" << endl;
pRoot->Remove(pComposite);
pRoot->Operation(0);
delete pComposite;
delete pRoot;
}
运行结果:
6.1 组合Composite是一种基本对象Component(3.1)。
6.2 Leaf也是一种基本对象,只需要关注Component接口(3.2)。
6.2 继承Component接口,就可以增加新类型的组件(3.3)。