案例:公司管理分级结构
组合模式
组合模式简介(CompositePattern)
组合模式将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性
组合模式和装饰模式
组合模式和装饰模式都可以用来透明的把对象包装在具有同样接口的另一个对象中。
组合模式和装饰模式都是结构型模式。组合模式着眼于把众多子对象组织为一个整体;装饰模式着眼于在不修改现有对象或从其派生子类的前提下为其增添职责,其子对象只有一个
组合模式结构
- Component(抽象构件): 定义了叶子构件和容器构件的一些公共接口,是管理或者访问子构件的方法,具体的实现在叶子构件和容器构件中进行
- Leaf(叶子构件): 它表示树形结构中的叶子节点对象,叶子构件没有子节点,实现了在抽象构件中定义的行为。对于管理子构件的方法,叶子构件可以通过抛出异常、提示错误等方式进行处理。
- Composite(容器构件):容器构件一方面具体实现公共接口,另一方面聚合关系包含子构件
组合模式示例
https://gitee.com/NiMiKiss/design-pattern.git
#ifndef _COMPOSITE_PATTERN_
#define _COMPOSITE_PATTERN_
#include<iostream>
#include<vector>
class Company
{
public:
Company(const std::string& sCompanyName) :m_sCompanyName(sCompanyName) {}
std::string GetName() { return m_sCompanyName; }
virtual void Add(std::shared_ptr<Company> spCompany) = 0;
virtual void Remove(std::shared_ptr<Company> spCompany) = 0;
virtual void Display(const int iDepth) = 0;
virtual void LineOfDuty() = 0;
private:
std::string m_sCompanyName;
};
class ConcreteCompany :public Company
{
public:
ConcreteCompany(const std::string& sCompanyName) :Company(sCompanyName) {}
void Add(std::shared_ptr<Company> spCompany) { m_vecCompany.push_back(spCompany); }
void Remove(std::shared_ptr<Company> spCompany)
{
for (size_t i = 0; i < m_vecCompany.size(); i++)
{
if (m_vecCompany[i]->GetName() == spCompany->GetName())
{
m_vecCompany.erase(m_vecCompany.begin() + i);
}
}
}
void Display(const int iDepth)
{
std::cout << std::string(iDepth, '-') << GetName() << std::endl;
for (size_t i = 0; i < m_vecCompany.size(); ++i)
{
m_vecCompany[i]->Display(iDepth + 2);
}
}
void LineOfDuty()
{
for (size_t i = 0; i < m_vecCompany.size(); ++i)
{
m_vecCompany[i]->LineOfDuty();
}
}
private:
std::vector<std::shared_ptr<Company>> m_vecCompany;
};
class HRDepartment :public Company
{
public:
HRDepartment(const std::string& sCompanyName) :Company(sCompanyName) {}
void Add(std::shared_ptr<Company> spCompany) { std::cout << "not support!" << std::endl; }
void Remove(std::shared_ptr<Company> spCompany) { std::cout << "not support!" << std::endl; }
void Display(const int iDepth)
{
std::cout << std::string(iDepth, '-') << GetName() << std::endl;
}
void LineOfDuty()
{
std::cout << GetName() << "员工招聘培训管理" << std::endl;
}
};
class FinanceDepartment :public Company
{
public:
FinanceDepartment(const std::string& sCompanyName) :Company(sCompanyName) {}
void Add(std::shared_ptr<Company> spCompany) { std::cout << "not support!" << std::endl; }
void Remove(std::shared_ptr<Company> spCompany) { std::cout << "not support!" << std::endl; }
void Display(const int iDepth)
{
std::cout << std::string(iDepth, '-') << GetName() << std::endl;
}
void LineOfDuty()
{
std::cout << GetName() << "公司财务收支管理" << std::endl;
}
};
#endif // !_COMPOSITE_PATTERN_
客户端调用
#include "Composite_Pattern.h"
#include<iostream>
int main()
{
auto spRoot = std::shared_ptr<ConcreteCompany>(new ConcreteCompany("北京总公司"));
spRoot->Add(std::shared_ptr<HRDepartment>(new HRDepartment("总公司人力资源部")));
spRoot->Add(std::shared_ptr<FinanceDepartment>(new FinanceDepartment("总公司财务部")));
auto spConcreteCompany_0 = std::shared_ptr<ConcreteCompany>(new ConcreteCompany("上海华东分公司"));
spConcreteCompany_0->Add(std::shared_ptr<HRDepartment>(new HRDepartment("华东分公司人力资源部")));
spConcreteCompany_0->Add(std::shared_ptr<FinanceDepartment>(new FinanceDepartment("华东分公司财务部")));
spRoot->Add(spConcreteCompany_0);
auto spConcreteCompany_1 = std::shared_ptr<ConcreteCompany>(new ConcreteCompany("南京办事处"));
spConcreteCompany_1->Add(std::shared_ptr<HRDepartment>(new HRDepartment("南京办事处人力资源部")));
spConcreteCompany_1->Add(std::shared_ptr<FinanceDepartment>(new FinanceDepartment("南京办事处财务部")));
spConcreteCompany_0->Add(spConcreteCompany_1);
auto spConcreteCompany_2 = std::shared_ptr<ConcreteCompany>(new ConcreteCompany("杭州办事处"));
spConcreteCompany_2->Add(std::shared_ptr<HRDepartment>(new HRDepartment("杭州办事处人力资源部")));
spConcreteCompany_2->Add(std::shared_ptr<FinanceDepartment>(new FinanceDepartment("杭州办事处财务部")));
spConcreteCompany_0->Add(spConcreteCompany_2);
std::cout << "结构图:" << std::endl;
spRoot->Display(1);
std::cout << "职责:" << std::endl;
spRoot->LineOfDuty();
return EXIT_SUCCESS;
}