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)。