组合模式

简介

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

总部、分部和办事处是成树状结构,也就是有组织结构的,不可以简单的平行管理。
希望总公司的组织结构,比如人力资源部、财务部的管理功能可以复用于分公司。这其实是整体与部分可以被一致对待的问题。
适用性

想表示对象的“部分-整体”层次结构。
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
结构


参与者

Component
为组合中的对象声明接口。
在适当的情况下,实现所有类共有接口的缺省行为。
声明一个接口用于访问和管理Component的子组件。
在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。(可选)
Leaf
在组合中表示叶节点对象,叶节点没有子节点。
在组合中定义叶节点对象的行为。
Composite
定义有子部件的那些部件的行为。
存储子部件。
在Component接口中实现与子部件有关的操作。
Client
通过Component接口操纵组合部件的对象。

协作

用户使用Component类接口与组合结构中的对象进行交互。
如果接收者是一个叶节点,则直接处理请求。
如果接收者是一个Composite,它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。
效果

定义了包含基本对象和组合对象的类层次结构。
简化客户代码。
使得更容易添加新类型的组件。

职责链模式

简介

为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求。
将这些对象连成一条链,并沿着这条链传递该请求,指导有一个对象处理它为止。
动机

考虑公司中的请假申请。
公司中管理人员按等级从低到高分别有:经理、总监、总经理。
请假需要根据天数长短,向不同等级的管理人员申请,例如少于2天直接向经理申请即可,少于一周必须要总监批准,更长时间则需要总经理批准。
适用性

有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。
结构

参与者

Handler
定义一个处理请求的接口。
实现后继链。
ConcreteHandler
处理它所负责的请求。
可访问它的后继者。
如果可处理该请求,就处理之;否则将该请求转发给它的后继者。
Client
向链上的ConcreteHandler对象提交请求。
效果

降低耦合度。
增强了给对象指派职责的灵活性。
不保证被接受。

实例

根据下图,利用组合模式构建该公司的结构。

即总公司下设上海华东分公司,华东分公司下设南京办事处和杭州办事处。其中,各级分公司均设有人力资源部和财务部。

利用组合模式构建好该结构后,利用职责链模式处理各地员工加薪请求。

例如,一南京员工提出加薪请求,如果加薪不超过1000元,南京办事处即可批准;如果超过1000元,则上报华东分公司,如果2000元以内,则批准;超过则上报北京总公司,如果不超过3000元,则总公司批准,否则拒绝。

UML

组合模式Component是对象声明接口,对应于职责链模式的Handler,两个模式的代码可以合并。

另外通过增加low, bound两个变量来控制if语句数量,减少类的数目。因此职责链中的多个ConcreteHandler对应于一个具体的ConcreteCompany。

代码

#include<iostream>
#include<list>
#include <typeinfo>using namespace std;class Component{public:Component(string name){this->name = name;}virtual void Add(Component* c) = 0;virtual void Remove(Component* c) = 0;virtual void Display(int depth) = 0;void SetSuccessor(Component* s){this->successor = s;}void SetBound(int low, int high){this->low = low;this->high = high;}virtual void HandleReauest(int request) = 0;
protected:string name;int low, high;Component* successor;
};class Subcom : public Component{public:Subcom(string name) : Component(name){}void Add(Component* c){cout<<"Cannot add to a leaf";}void Remove(Component* c){cout<<"Cannot remove from a leaf";}void Display(int depth){for(int i = 0; i <= depth; i++)cout<<"--";cout<<name<<endl;}void HandleReauest(int request){}
};class ConcreteCompany: public Component{private:list<Component*> children;
public:ConcreteCompany(string name): Component(name){}void Add(Component *c){children.push_back(c);}void Remove(Component *c){children.remove(c);}void Display(int depth){for(int i = 0; i <= depth; i++)cout<<"--";cout<<name<<endl;for(Component* child : children){child->Display(depth + 1);}}void HandleReauest(int request){if(request >= low && request <= high){cout<<this->name<<"处理请求: "<<request<<endl;}else if(successor != NULL){cout<<this->name<<"处理失败"<<endl;successor->HandleReauest(request);}else{cout<<this->name<<"加薪拒绝"<<request<<endl;}}
};/*
即总公司下设上海华东分公司,华东分公司下设南京办事处和杭州办事处。其中,各级分公司均设有人力资源部和财务部。用组合模式构建好该结构后,利用职责链模式处理各地员工加薪请求。例如,一南京员工提出加薪请求,如果加薪不超过1000元,南京办事处即可批准;如果超过1000元,则上报华东分公司,如果2000元以内,则批准;超过则上报北京总公司,如果不超过3000元,则总公司批准,否则拒绝。、实验报告内容:    */int main(){Component *root = new ConcreteCompany("总公司");root->Add(new Subcom("人力资源部"));root->Add(new Subcom("财务部"));root->SetBound(2000, 3000);Component *huadong = new ConcreteCompany("上海华东分公司");huadong->Add(new Subcom("人力资源部"));huadong->Add(new Subcom("财务部"));huadong->SetBound(1000, 2000);Component *nanjing = new ConcreteCompany("南京办事处");nanjing->Add(new Subcom("人力资源部"));nanjing->Add(new Subcom("财务部"));nanjing->SetBound(0, 1000);Component *hanzhou = new ConcreteCompany("杭州办事处");hanzhou->Add(new Subcom("人力资源部"));hanzhou->Add(new Subcom("财务部"));hanzhou->SetBound(0, 1000);nanjing->SetSuccessor(huadong);hanzhou->SetSuccessor(huadong);huadong->SetSuccessor(root);root->SetSuccessor(NULL);huadong->Add(nanjing);huadong->Add(hanzhou);root->Add(huadong);root->Display(1);cout<<"*********************"<<endl;nanjing->HandleReauest(100);cout<<"*********************"<<endl;hanzhou->HandleReauest(1500);cout<<"*********************"<<endl;hanzhou->HandleReauest(2100);cout<<"*********************"<<endl;hanzhou->HandleReauest(3100);return 0;
}
//

结果

总结

①本次需要将职责链模式与组合模式合并,其中组合模式Component是对象声明接口,对应于职责链模式的Handler。

②组合模式中的节点需要放到当前父节点的list中,对于容器list,需要掌握对应的STL语句。

③对于职责链模式,为了减少类的数量和耦合需要设置low和high两个上下界。类虽然少了,但是对象没有减少,这些对象形成一条链,并沿着这条链传递该请求,直到有一个对象处理了它为止。通过当前对象的name来指示客户端选择。

更多内容访问 omegaxyz.com
网站所有代码采用Apache 2.0授权
网站文章采用知识共享许可协议BY-NC-SA4.0授权
© 2019 • OmegaXYZ-版权所有 转载请注明出处

组合模式与职责链模式编程实现相关推荐

  1. JAVA 设计模式—————— 命令模式和职责链模式

    学习 Netty 前的准备工作!! 这里,还是先来复习一下 OOP (面向对象)的七大原则: 开闭原则:对扩展开放,对修改关闭 里氏替换原则:继承必须确保超类所拥有的性质在子类中仍然成立. 依赖倒置原 ...

  2. 责任链模式(职责链模式)详解——小马同学@Tian

    责任链模式(职责链模式)详解 在现实生活中,一个事件需要经过多个对象处理是很常见的场景.例如,采购审批流程.请假流程等.公司员工请假,可批假的领导有部门负责人.副总经理.总经理等,但每个领导能批准的天 ...

  3. 策略模式和职责链模式在CMS中的应用

    最近在做一个轻量级CMS供客户站点使用. 根据客户的需求,需要以静态页方式提供用户浏览的页面,同时还要保留一个本份,支持"双远程"发布,即在一台远程发布服务器上保留存根,最终页面保 ...

  4. Java设计模式——责任链模式(职责链模式)详解

    模式的定义与特点 责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链:当 ...

  5. JAVA设计模式之责任链模式(职责链模式)

    转自JAVA设计模式之责任链模式(职责链模式)​​​​​​​ 责任链/职责链(Chain of Responsibility)模式的定义 为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理 ...

  6. 责任链模式(职责链模式)详解

    在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同.例如,公司员工请假,可批假的领导有部门负责人.副总经理.总经理等,但每个领导能批准的天数不同,员工必须根 ...

  7. 图解Java设计模式学习笔记——行为型模式(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式)

    一.模板方法模式(模板模式)--钩子方法 1.需求-豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材-->添加配料-->浸泡-->放到豆浆机打碎. 通过添加不同的配料 ...

  8. 设计模式之责任链模式(职责链模式)

    前言 在现实生活中,一个事件需要经过多个对象处理是很常见的场景.例如,采购审批流程.请假流程等.公司员工请假,可批假的领导有部门负责人.副总经理.总经理等,但每个领导能批准的天数不同,员工必须根据需要 ...

  9. 责任链模式(职责链模式)

    目录 一.模式的定义与特点 优点: 缺点: 二.模式的结构与实现 1. 模式的结构 2. 模式的实现 前言:         在现实生活中,一个事件需要经过多个对象处理是很常见的场景.例如,采购审批流 ...

  10. 观察者模式与职责链模式的相同和不同_GOF设计模式(策略模式,职责链模式)...

    策略模式(整体的替换算法) 基本介绍:对象具备某个行为,但是在不同的场景中,该行为有不同的实现算法.(定义一组算法,将每个算法都封装起来,并且使他们之间可以互换).多用于封装算法 类图 角色: 上下文 ...

最新文章

  1. java 中线程的状态
  2. 栈的应用_DFS解迷宫问题
  3. EntityFramework 7 OrderBy Skip Take-计算排序分页 SQL 翻译
  4. C#桌面开发的未来WebWindow
  5. 34 年了,“杀”不死的 Perl!
  6. 为什么美团全面推动 K8S 落地,咬紧牙关也要搞云原生?
  7. mongodb系列~mongodb的副本集搭建和原理
  8. 今天发现的好几个PP文字,不敢独享,gaga
  9. 2n皇后的问题java_蓝桥杯java 基础练习 2n皇后问题
  10. Nginx https configuration backed Certbot
  11. Linux内核部件分析 设备驱动模型之device
  12. 美国飞机安全事件频发:背后黑手竟然是5G?
  13. IEEE会议文章接收后提交流程
  14. attrib批量显示文件夹_BAT遍历目录并去掉文件夹隐藏属性
  15. ssh介绍和使用--SecureCRT工具和ssh命令使用,以及sshd配置
  16. Android View 获取焦点
  17. kali linux渗透测试(一) --- set社工攻击
  18. 谷歌浏览器如何开启暗黑模式
  19. 电脑游戏录屏哪个好用免费?这2款录屏软件,用过都说好!
  20. 何谓光电传感器-看看基恩士如何说

热门文章

  1. 40个经典单片机实验_太经典啦!单片机常用的14个C语言算法(附详细代码)
  2. Linux文件的基本属性
  3. c语言静态数组是什么意思,C语言静态数组实现栈操作
  4. Linux内核安全包括哪些内容,Linux内核安全更新怎么样 解决了哪些问题
  5. tsm linux文件备份命令,IBM TSM简单使用文档
  6. c++ string replace_「Java学习」String,StringBuffer和StringBuilder的区别
  7. huffman树_Java使用哈夫曼树实现文件压缩的原理及实现
  8. Java编程:排序算法——冒泡排序
  9. Java编程:约瑟夫问题——单向环形链表
  10. Javascript:自定义构造函数的优化