组合模式

定义

将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式是的用户对单个对象和组合对象的使用具有一致性。

动机

当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合对象结构中的所有对象时,就应该考虑用组合模式了。

UML类图

场景拆解

以一个大型公司为需求背景,组织我们的代码。一个北京总公司,下面有郑州和西安两个分公司。然后每个公司不管是总公司还是分公司都有自己的人力资源部,IT部和市场部。

源码实现

  • component.h
#ifndef COMPONENT_H
#define COMPONENT_H
#include <QList> class Component
{
public:
Component(QString name);
virtual ~Component();
virtual void add(Component* com, int depth = 0) = 0;
virtual void remove(Component* com) = 0;
virtual void display() = 0;
virtual void LineOfDuty() = 0; QString name();
void setDepth(int depth);
int depth();
private:
QString m_Name;
int m_Depth;
}; class ConcreteCompany : public Component
{
public:
ConcreteCompany(QString name);
virtual ~ConcreteCompany();
virtual void add(Component* com, int depth = 0);
virtual void remove(Component* com);
virtual void display();
virtual void LineOfDuty();
private:
QList<Component*> m_ChildCom;
}; class HumanResource : public Component
{
public:
HumanResource(QString name);
virtual ~HumanResource();
virtual void add(Component* com, int depth = 0);
virtual void remove(Component* com);
virtual void display();
virtual void LineOfDuty();
}; class IT : public Component
{
public:
IT(QString name);
virtual ~IT();
virtual void add(Component* com, int depth = 0);
virtual void remove(Component* com);
virtual void display();
virtual void LineOfDuty();
}; class Marketing : public Component
{
public:
Marketing(QString name);
virtual ~Marketing();
virtual void add(Component* com, int depth = 0);
virtual void remove(Component* com);
virtual void display();
virtual void LineOfDuty();
};
#endif // COMPONENT_H
  • component.cpp
/************************************
* @brief : 安排一下故事背景:有一个王者农药全国总公司在深圳,现在想要在全国开办事处
* 1.北京办事处- 招聘部,研发部,市场部
* 2.郑州办事处- 招聘部,研发部,市场部
* 3.西安办事处- 招聘部,研发部,市场部
* and so on...
* @author : wzx
* @date : 2020-05-11
* @project : Composite
*************************************/
#include <QDebug>
#include "component.h" #define DELETEOBJECT(x) if(x) { delete x; x = nullptr; } Component::Component(QString name):m_Name(name) {} Component::~Component(){} QString Component::name()
{
return m_Name;
} void Component::setDepth(int depth)
{
m_Depth = depth;
} int Component::depth()
{
return m_Depth;
} ConcreteCompany::ConcreteCompany(QString name)
: Component(name)
{ } ConcreteCompany::~ConcreteCompany()
{
for(auto com : m_ChildCom)
{
DELETEOBJECT(com);
}
m_ChildCom.clear();
} void ConcreteCompany::add(Component* com, int depth)
{
com->setDepth(depth);
m_ChildCom.append(com);
} void ConcreteCompany:: remove(Component* com)
{
m_ChildCom.removeOne(com);
} void ConcreteCompany::display()
{
QString str;
for(int n = 0; n < depth(); ++n)
str += "--";
qDebug() << qPrintable(str) << (name());
for(auto com : m_ChildCom)
{
com->display();
}
} void ConcreteCompany::LineOfDuty()
{ } HumanResource::HumanResource(QString name)
: Component(name)
{ } HumanResource::~HumanResource()
{ } void HumanResource::add(Component* com, int depth)
{
com->setDepth(depth);
} void HumanResource::remove(Component* com)
{ } void HumanResource::display()
{
QString str;
for(int n = 0; n < depth(); ++n)
str += "--";
qDebug() << qPrintable(str) << (name());
} void HumanResource::LineOfDuty()
{
qDebug() << "人力资源部,负责招聘";
} IT::IT(QString name)
: Component(name)
{ } IT::~IT()
{ } void IT::add(Component* com, int depth)
{
com->setDepth(depth);
} void IT::remove(Component* com)
{ } void IT::display()
{
QString str;
for(int n = 0; n < depth(); ++n)
str += "--";
qDebug() << qPrintable(str) << (name());
} void IT::LineOfDuty()
{
qDebug() << "IT部门,负责写代码";
} Marketing::Marketing(QString name)
: Component(name)
{ } Marketing::~Marketing()
{ } void Marketing::add(Component* com, int depth)
{
com->setDepth(depth);
} void Marketing::remove(Component* com)
{ } void Marketing::display()
{
QString str;
for(int n = 0; n < depth(); ++n)
str += "--";
qDebug() << qPrintable(str) << name();
} void Marketing::LineOfDuty()
{
qDebug() << "市场部门,负责市场推广";
}
  • main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "component.h" int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); Component* root = new ConcreteCompany("北京总部");
root->setDepth(0);
root->add(new HumanResource("人力资源部门"), 1);
root->add(new IT("IT部门"), 1);
root->add(new Marketing("市场部门"), 1); Component* zz = new ConcreteCompany("郑州办事处");
zz->add(new HumanResource("人力资源部门"), 2);
zz->add(new IT("IT部门"), 2);
zz->add(new Marketing("市场部门"), 2);
root->add(zz, 1); Component* xa = new ConcreteCompany("西安办事处");
xa->add(new HumanResource("人力资源部门"), 2);
xa->add(new IT("IT部门"), 2);
xa->add(new Marketing("市场部门"), 2);
root->add(xa, 1); root->display();
return a.exec();
}
  • 运行结果

"北京总部"

-- "人力资源部门"

-- "IT部门"

-- "市场部门"

-- "郑州办事处"

---- "人力资源部门"

---- "IT部门"

---- "市场部门"

-- "西安办事处"

---- "人力资源部门"

---- "IT部门"

---- "市场部门"

优点

组合模式定义了包含基本对象和组合对象的类层次结构。基本对象可以组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。

缺点

参考《大化设计模式》

最新文章

  1. 不要着急改代码,先想想--centos 6.8下编译安装tmux
  2. MVC3 数据验证用法之密码验证设计思路
  3. depot用例视图建模
  4. (转) RSA算法原理(一)
  5. Entity Framework 第九篇 关于自增列的事务处理
  6. 简单的鼠标可拖动div 兼容IE/FF
  7. MySql语句大全:创建、授权、查询、修改等
  8. [React Native] Build a Github Repositories component
  9. ZOJ 2110 Tempter of the Bone(DFS)
  10. oracle常用自定义函数集合
  11. 分享毕业学生“ERP实施project联赛”总结,是肺腑之言——知识是人的价值的体现,每门课程是有意义的学校纪律
  12. 通过HttpURLConnection模拟post表单提交
  13. 【从翻译mos文章】在OGG (Oracle GoldenGate) 正在使用SCHEMATRANDATA如果,需要额外的db patch
  14. SpringBoot学习之SpringBoot执行器
  15. linux-基础命令篇-02
  16. String类中&quot;==&quot;、equals和普通类中&quot;==&quot;、equals的比较
  17. 关于git 命令的一些事
  18. Jmeter接口测试实例图文示例
  19. PHP 基础篇 - PHP 正则官方文档汇总
  20. jreble安装 in idea

热门文章

  1. PHP函数:debug_backtrace
  2. SpringBoot集成Shiro实现权限控制
  3. 2. Git-命令行-删除本地和远程分支
  4. Mysql使用终端操作数据库
  5. Spring5:IOC注解
  6. json:格式化数据
  7. pytorch Dataset数据集和Dataloader迭代数据集
  8. Springboot整合https原来这么简单
  9. nginx history路由模式时,页面返回404重定向index.html
  10. 在c++中引用c头文件里的函数