文章目录
- 组合模式应用场景
- 组合模式概念
- 组合模式结构图
- 透明方式和安全方式
- 什么时候使用组合模式
- 公司管理系统使用 组合模式来构架
- 组合模式的好处
组合模式应用场景
整体和部分可以被一致性对待 比如人力资源部 财务部的管理功能可以复用于分公司的功能
可以引入一种 树状的结构 来统一管理
组合模式概念
组合模式(Composite),将对象组合成树形结构以表示“部分 - 整体” 的层次结构。组合模式是的用户对单个对象和组合对象的使用具有一致性。
组合模式结构图
#include <iostream>
#include <list>
using namespace std;
//组合中对象声明接口 实现所有类共有的默认接口行为
class Component {
public:
Component(string name)
{
this->name = name;
}
virtual void Add(Component *c) {};
virtual void Remove(Component* c) {};
virtual void Display(int depth) {};//展示参数表示数的深度
protected:
string name;
};
// 在组合里面表示叶子节点对象 叶节点没有子节点
class Leaf :public Component
{
public:
Leaf(string name) :Component(name) {
}
void Add(Component* c) override {
cout << "cannot add to a leaf " << endl;
}
void Remove(Component* c) override {
cout << "cannot Remove from a leaf " << endl;
}
void Display(int depth) override {
string a = string(depth, '-');
cout << a << name << endl;
}
};
//在组合里面定义有子节点行为 用来存储子部件
class Composite : public Component
{
public:
Composite(string name) :Component(name) {
}
void Add(Component *c) override {
children.push_back(c);
}
void Remove(Component *c) override {
children.remove(c);
}
void Display(int depth)override
{
cout << string(depth, '-') << name << endl;
for (auto Com : children)
{
Com->Display(depth + 2);
}
}
private:
list<Component*> children;
};
int main()
{
Composite * root = new Composite("root");
root->Add(new Leaf("Leaf A"));
root->Add(new Leaf("Leaf B"));
Composite* comp = new Composite("Composite X");
comp->Add(new Leaf("Leaf XA"));
comp->Add(new Leaf("Leaf XB"));
root->Add(comp);
Composite *comp2 = new Composite("Composite XY");
comp2->Add(new Leaf("Leaf XYA"));
comp2->Add(new Leaf("Leaf XYB"));
comp->Add(comp2);
root->Add(new Leaf("Leaf C"));
Leaf * leaf = new Leaf("Leaf D");
root->Add(leaf);
root->Remove(leaf);
root->Display(1);
return 0;
}
代码运行结果能显示出 树状的组件
透明方式和安全方式
透明方式
在这种实现里面 Component 中声明了所有用来管理子对象的方法 对于外界来说 叶子节点和子节点没有区别 它们具有完全一样的接口 Leaf 本身不具备Add Remove方法 所以实现它是没有任何意义的
安全方式
在Component里面不去声明Add 和 Remove方法 这样子类Left不需要去实现,而是在Composite声明所有用来管理子类对象的方法 这样做就不会遇到刚才遇到的问题 但是由于不够透明 所以树枝类将不具有相同的接口 客户端的调用需要做判断
应该视情况 来决定使用哪一种方式
什么时候使用组合模式
需求中体现部分和整体层次的结构的时候 希望用户可以忽略组合对象和单个对象的不同,统一地使用组合结构中的所有对象时 ,就应该考虑使用组合模式了
TreeView 控件使用的就是组合模式
公司管理系统使用 组合模式来构架
#include <iostream>
#include <list>
using namespace std;
//组合中对象声明接口 实现所有类共有的默认接口行为
class Company {
public:
Company(string name)
{
this->name = name;
}
virtual void Add(Company *c) = 0;
virtual void Remove(Company* c) = 0;
virtual void Display(int depth) =0 ;//展示参数表示数的深度
virtual void LineOfDuty() =0; //履行职责
protected:
string name;
};
// 人力资源部门
class HRDepartment :public Company
{
public:
HRDepartment(string name) :Company(name) {
}
void Add(Company* c) override {
cout << "cannot add to a leaf " << endl;
}
void Remove(Company* c) override {
cout << "cannot Remove from a leaf " << endl;
}
void Display(int depth) override {
string a = string(depth, '-');
cout << a << name << endl;
}
void LineOfDuty()override
{
cout << name<<" 员工招聘培训管理 " << endl;
}
};
//具体公司类 实现接口 树枝节点
class ConcreteCompany : public Company
{
public:
ConcreteCompany(string name) :Company(name) {
}
void Add(Company *c) override {
children.push_back(c);
}
void Remove(Company *c) override {
children.remove(c);
}
void Display(int depth)override
{
cout << string(depth, '-') << name << endl;
for (auto Com : children)
{
Com->Display(depth + 2);
}
}
//履行职责
void LineOfDuty() override {
for (auto Com : children)
{
Com->LineOfDuty();
}
}
private:
list<Company*> children;
};
//财务部
class FinanceDepartment :public Company
{
public:
FinanceDepartment(string name) :Company(name) {
}
void Add(Company* c) override {
cout << "cannot add to a leaf " << endl;
}
void Remove(Company* c) override {
cout << "cannot Remove from a leaf " << endl;
}
void Display(int depth) override {
string a = string(depth, '-');
cout << a << name << endl;
}
void LineOfDuty()override
{
cout << name << " 公司财务收支管理 " << endl;
}
};
int main()
{
ConcreteCompany * root = new ConcreteCompany("北京总公司");
root->Add(new HRDepartment("总公司人力资源"));
root->Add(new HRDepartment("总公司财务部门"));
ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
comp->Add(new HRDepartment("华东分公司人力资源部"));
comp->Add(new HRDepartment("华东分公司财务部"));
root->Add(comp);
ConcreteCompany *comp2 = new ConcreteCompany("南京办事处");
comp2->Add(new HRDepartment("南京办事处人力资源部"));
comp2->Add(new HRDepartment("南京办事处财务部"));
comp->Add(comp2);
ConcreteCompany* comp1 = new ConcreteCompany("杭州办事处");
comp1->Add(new HRDepartment("杭州办事处人力资源部"));
comp1->Add(new HRDepartment("杭州办事处财务部"));
comp->Add(comp1);
cout << "结构图 :" << endl;
root->Display(1);
cout << "职责:" << endl;
root->LineOfDuty();
return 0;
}
运行后的结果图
组合模式的好处
组合模式定义基本对象和分公司 办事处结合对象的类层次结构 基本对象可以被组合成更复杂的类型
组合对象又可以被组合 这样不断地柜下去 客户代码 任何用到基本对象的地方都可以使用组合对象
组合模式让客户可以一致的使用组合结构和单个对象