组合
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
适用性
- 你想表示对象的部分-整体层次结构。
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
示例情境
很多种不同的菜单,但又都是菜单。
典型的Composite对象结构
结构
Component - 为组合中的对象声明接口。在适当的情况下,实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子组件。(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
Leaf - 在组合中表示叶节点对象,叶节点没有子节点。在组合中定义图元对象的行为。
Composite - 定义有子部件的那些部件的行为。存储子部件。在Component接口中实现与子部件有关的操作。
Client - 通过Component接口操纵组合部件的对象。
协作:
用户使用Component类接口与组合结构中的对象进行交互。如果接受者是一个叶节点,则直接处理请求。如果接受者是Composite,它通常将请求发送给它的子部件,在转发请求之前/之后可能执行一些辅助操作。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <iostream> #include <vector> #include <algorithm>
class Component { public: virtual void operation(){} virtual void add(Component* m) { m_children.push_back(m); } virtual void remove(Component* m) { m_children.erase(std::remove(m_children.begin(), m_children.end(), m), m_children.end()); } virtual Component* get_child(int n) { if (n >= m_children.size()) return NULL; return m_children[n]; } protected: std::vector<Component*> m_children; };
class Leaf : public Component { public: virtual void operation() { std::cout<<"I'm Leaf."<<std::endl; } };
class Composite : public Component { public: virtual void operation() { std::cout<<"In the Composite: "<<std::endl; for (std::vector<Component*>::iterator it = m_children.begin(); it != m_children.end(); ++it) { if (!(*it)) continue; (*it)->operation(); } } };
class Client { public: void test() { Composite composite; Leaf leaf1, leaf2; composite.add(&leaf1); composite.add(&leaf2); composite.operation(); } };
int main() { Client c; c.test(); system("Pause"); }
|
相关模式
- 通常部件-父部件连接用于Responsibility of Chain模式。
- Decorator模式经常与Composite模式一起使用。当装饰和组合一起使用时,它们通常有一个公共的父类。因此装饰必须支持具有Add、Remove和GetChild操作的Component接口。
- Flyweight让你共享组件,但不再能引用他们的父部件。
- Iterator可用来遍历Composite。
- Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。
[1] 设计模式:可复用面向对象软件的基础
[2] Head First 设计模式