索引目录
1 含义
组合多个对象形成树形结构以表示“部分-整体”的结构层次。组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。
2 模式结构
3 代码实现
举例:假设你要开一家公司,要招募大量员工,当然有经理,主管,普通员工,相信再小的公司都会有这样的组织架构。经理管主管,主管又管普通员工,普通员工自己管自己
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//员工:抽象对象Component
class Employee
{
protected:
string m_Name;
string m_job;
public:
Employee(string name,string job):m_Name(name),m_job(job){}
virtual void add(Employee* subordinate) = 0;
virtual void remove(Employee*subordinate) = 0;
virtual void showMe()=0;
};
//设计员
class Designer: public Employee
{
public:
Designer(string name,string job):Employee(name,job){}
void add(Employee* subordinate) override
{
cout << "我是小员工,管理不了人!" << endl;
}
void remove(Employee*subordinate)override
{
cout << "我是小员工,没人归我管理!" << endl;
}
void showMe()override
{
cout << "姓名:" << m_Name << "--" << "职位:" << m_job << endl;;
}
};
//主管或经理:枝节点实现
class Manger :public Employee
{
private:
vector<Employee*>m_Subordinates;
public:
Manger(string name, string job) :Employee(name, job) {}
void add(Employee* subordinate) override
{
m_Subordinates.push_back(subordinate);
}
void remove(Employee* subordinate) override
{
vector<Employee*>::iterator it = m_Subordinates.begin();
while (it!=m_Subordinates.end())
{
if(*it==subordinate)
{
m_Subordinates.erase(it);
delete subordinate;
subordinate = nullptr;
break;
}
it++;
}
}
//显示自己及手下
void showMe()override
{
cout << "姓名:" << m_Name << "--" << "职位:" << m_job << endl;
cout << m_Name << "手下有:";
//显示子节点
vector<Employee*>::iterator it = m_Subordinates.begin();
while (it != m_Subordinates.end())
{
(*it)->showMe();
++it;
}
}
};
int main()
{
//招收员工,从上到下
Employee *manager = new Manger("小强", "经理");
Employee *supervisor = new Manger("小明", "主管");
Employee *supervisor1 = new Manger("小英", "主管");
Employee *staff1 = new Designer("小李", "设计员");
Employee *staff2 = new Designer("小王", "设计员");
//组织公司架构
manager->add(supervisor);
manager->add(supervisor1);
supervisor->add(staff1);
supervisor1->add(staff2);
manager->showMe();
staff2->add(manager);
return 0;
}
4 优缺点
优点:
利用多态和递归机制更方便地使用复杂树结构。
缺点:
对于功能差异较大的类, 提供公共接口或许会有困难。 在特定情况下, 你需要过度一般化组件接口, 使其变得令人难以理解。
5 适用场景
需要实现树状对象结构, 可以使用组合模式
6.模式扩展
桥接模式、 状态模式和策略模式 (在某种程度上包括适配器模式) 模式的接口非常相似。 实际上, 它们都基于组合模式——即将工作委派给其他对象, 不过也各自解决了不同的问题。 模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。
你可以在创建复杂组合树时使用生成器模式, 因为这可使其构造步骤以递归的方式运行。
责任链模式通常和组合模式结合使用。 在这种情况下, 叶组件接收到请求后, 可以将请求沿包含全体父组件的链一直传递至对象树的底部。
你可以使用迭代器模式来遍历组合树。
你可以使用访问者模式对整个组合树执行操作。
你可以使用享元模式实现组合树的共享叶节点以节省内存。
组合和装饰模式的结构图很相似, 因为两者都依赖递归组合来组织无限数量的对象。
装饰类似于组合, 但其只有一个子组件。 此外还有一个明显不同: 装饰为被封装对象添加了额外的职责, 组合仅对其子节点的结果进行了 “求和”。
但是, 模式也可以相互合作: 你可以使用装饰来扩展组合树中特定对象的行为。
大量使用组合和装饰的设计通常可从对于原型模式的使用中获益。 你可以通过该模式来复制复杂结构, 而非从零开始重新构造。
参考
1.https://refactoringguru.cn/design-patterns/composite
2.https://blog.csdn.net/a369189453/article/details/81193415
3.https://blog.csdn.net/lxq1997/article/details/89460373