文章目录
- 组合模式应用场景
- 组合模式概念
- 组合模式结构图
- 透明方式和安全方式
- 什么时候使用组合模式
- 公司管理系统使用 组合模式来构架
- 组合模式的好处
组合模式应用场景
整体和部分可以被一致性对待 比如人力资源部 财务部的管理功能可以复用于分公司的功能
可以引入一种 树状的结构 来统一管理
组合模式概念
组合模式(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;
}
运行后的结果图
组合模式的好处
组合模式定义基本对象和分公司 办事处结合对象的类层次结构 基本对象可以被组合成更复杂的类型
组合对象又可以被组合 这样不断地柜下去 客户代码 任何用到基本对象的地方都可以使用组合对象
组合模式让客户可以一致的使用组合结构和单个对象