组合模式(Composite Pattern):将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式:
逻辑分析:
组合模式包含以下主要角色。
- 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
- 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
定义一个抽象类,两个子类,一个作为树枝节点,一个作为树叶节点,树枝节点负责控制叶子节点
使用场景:
可以实现管理公司部门层级,人员管理的场景。
源码demo:
类似于树的节点依次管理,可以实现公司部门人员的管理。
/************************************************************************* 组合模式: 是把单个对象和组合对象放在一起使用,把操作单个对象,和操作整个对象搞的没有太大差别 在遍历的时候,如果存储的是叶子结点,那么调用叶子结点的显示函数 如果存储的是组合对象,那么递归调用自己的显示函数 实现方式: 定义单个对象和一组对象的接口,提供统一的操作函数 在定义结点的时候,都将其创建出的对象,使用抽象类指针,指向这个创建的对象, 然后将此指针,添加到相对应的结点。 ***************************************************************************/ #include <iostream> #include <vector> #include <string> using namespace std; class Component { public: Component(string name){this->name = name;} virtual void add(Component *) = 0; virtual void remove(Component *) = 0; virtual void display(int) = 0; public: string name; }; class Leaf :public Component { public://子类继承父类,父类初始化要使用初始化列表 Leaf(string name) :Component(name){} void add(Component *c) { cout << "leaf cannot add" << endl;} void remove(Component *c) { cout << "leaf cannot remove" << endl; } void display(int depth) { string str(depth, '-'); str += name; cout << str << endl; } }; class Composite :public Component { private: vector<Component*> component; public: Composite(string name) :Component(name){} void add(Component *c) { component.push_back(c);//容器操作,将其放入容器 } void remove(Component *c) { for (vector<Component*>::iterator iter = component.begin(); iter != component.end(); iter++) { if (*iter == c) { component.erase(iter); } iter++; } } void display(int depth) { string str(depth, '-'); str += name;//在调用打印的时候先将组合结点的名字打印出来 cout << str << endl;//如果是组合结点直接打印 for (vector<Component*>::iterator iter = component.begin(); iter != component.end(); iter++) { (*iter)->display(depth + 1);//如果是叶子结点,那么调用叶子结点的打印函数,将此-符号数量加1传递给叶子结点进行打印 } //每次多向下递归一层,就多向下遍历加1 } }; int main() { Component *p = new Composite("小李");//组合结点Node中有一个vector向量 p->add(new Leaf("小王"));//这里面存储的是叶子结点,所以调用叶子结点的Display函数 p->add(new Leaf("小强")); Component *sub = new Composite("小虎");//在这里是把组合对象当成单个对象使用 sub->add(new Leaf("小王")); sub->add(new Leaf("小明")); sub->add(new Leaf("小柳")); p->add(sub); p->display(0);//在调用显示函数的时候,如果存储的是叶子结点,那么调用叶子结点的显示函数 //如果存储的是组合结点,那么递归调用组合结点的显示函数 sub->display(2); // system("pause"); return 0; }