組合模式,將對象組合成樹形結構以表示“部分-整體”的層次結構,組合模式使得用戶對單個對象和組合對象的使用具有一致性。
在自然界中常常存在著許多樹形關系,例如公司的結構,有子公司,部門。又如文件系統的結構,目錄下邊有目錄或者文件,而目錄下的目錄又有目錄和文件,如此遞歸下去。而組合模式就是為了處理這種樹形關系而存在的。
組合模式 天生就是為了表達樹形關系的,樹形關系的定義是遞歸的,故而組合模式的定義顯然也是遞歸的。組合模式的UML類圖如下:
在組合模式中存在三個角色:
Component 抽象構件類。該類給用戶提供了一個統一的視角,用戶可以對葉子和容器進行編程而無需在乎是葉子類或者是容器類。
Composite,容器構件類。容器構件類一方面可以提供操作如葉子類一樣,另一方面有可以包含子構件,子構建可以是容易構件也可以是葉子類。如果用文件系統來類比,容易構件類就是目錄。
Leaf,葉子類。葉子類可以提供功能操作,但是無法容納子構件。如果用文件系統來類比,葉子節點就是普通文件。
#include
#include
#include
#include
using std::string;
class Component {
public:
virtual ~Component (){};
virtual void operation() = 0;
virtual void add(Component *subComponent){}
virtual void remove(Component *subComponent){}
virtual Component *getChild(std::vector::size_type index){
return NULL;
}
};
class Leaf : public Component{
public:
virtual ~Leaf(){};
virtual void operation() override{
std::cout << "Here is leaf" << std::endl;
}
};
class Composite : public Component {
private:
std::vector children;
public:
virtual ~Composite (){
for(auto &child : children)
delete child;
};
virtual void operation() override{
std::cout << "Here is composite. childen : " << std::endl;
for (auto &child : children){
child->operation();
}
};
virtual void add(Component *subComponent) override{
children.push_back(subComponent);
}
virtual void remove(Component *subComponent) override{
auto ret = std::find(children.begin(), children.end(),
subComponent);
if (ret == children.end())
return;
children.erase(ret);
}
virtual Component *getChild(std::vector::size_type index) override{
if (index > children.size())
return nullptr;
return children[index];
}
};
int main(void)
{
Component *component = new Composite;
component->add(new Composite);
component->add(new Composite);
component->add(new Leaf);
component->add(new Leaf);
component->getChild(1)->add(new Leaf);
component->getChild(1)->add(new Leaf);
component->getChild(1)->add(new Leaf);
component->operation();
}
運行結果:
Here is composite. childen :
Here is composite. childen :
Here is composite. childen :
Here is leaf
Here is leaf
Here is leaf
Here is leaf
Here is leaf