索引

意图

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。

将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它位置。

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.

Chain the receiving objects and pass the request along the chain until an object handles it.

结构

一个典型的对象结构可能如下图所示:

参与者

Handler

  • 定义一个处理请求的接口。
  • 实现后继链

ConcreteHandler

  • 处理它所负责的请求。
  • 可访问它的后继者。
  • 如果可处理该请求,就处理;否则将该请求转发给它的后继者。

Client

  • 向链上的具体处理者对象提交请求。

适用性

在以下情况下可以使用 Chain of Responsibility 模式:

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

效果

  • 降低耦合度。对象无需知道哪个一个对象处理其请求,仅需知道对象被处理。
  • 增强了给对象指派职责的灵活性。可以运行时对该链进行动态增加或修改。

相关模式

  • Chain of Resposibility 常与 Composite 一起使用。一个构件的父构件可作为它的后继。

实现

实现方式(一):实现后继者链。

 namespace ChainOfResponsibilityPattern.Implementation1
{
public enum RequestCategory
{
Category1,
Category2,
} public abstract class Request
{
public abstract RequestCategory Category { get; }
public bool IsHandled { get; set; }
} public class ConcreteRequest1 : Request
{
public override RequestCategory Category
{
get { return RequestCategory.Category1; }
}
} public class ConcreteRequest2 : Request
{
public override RequestCategory Category
{
get { return RequestCategory.Category2; }
}
} public abstract class Handler
{
private Handler _successor; public Handler()
{
} public Handler(Handler successor)
{
_successor = successor;
} public void Handle(Request request)
{
OnHandle(request); if (!request.IsHandled)
{
if (_successor != null)
{
// pass request to successor
_successor.Handle(request);
}
}
} protected abstract void OnHandle(Request request);
} public class ConcreteHandler1 : Handler
{
public ConcreteHandler1()
{
} public ConcreteHandler1(Handler successor)
: base(successor)
{
} protected override void OnHandle(Request request)
{
if (request.Category == RequestCategory.Category1)
{
// handle the request which category is Category1
request.IsHandled = true;
}
}
} public class ConcreteHandler2 : Handler
{
public ConcreteHandler2()
{
} public ConcreteHandler2(Handler successor)
: base(successor)
{
} protected override void OnHandle(Request request)
{
if (request.Category == RequestCategory.Category2)
{
// handle the request which category is Category2
request.IsHandled = true;
}
}
} public class Client
{
public void TestCase1()
{
Request request1 = new ConcreteRequest1();
Request request2 = new ConcreteRequest2(); Handler handler2 = new ConcreteHandler2();
Handler handler1 = new ConcreteHandler1(handler2); handler1.Handle(request1);
handler1.Handle(request2);
}
}
}

设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。

设计模式之美:Chain of Responsibility(职责链)的更多相关文章

  1. 设计模式19:Chain Of Responsibility 职责链模式(行为型模式)

    Chain Of Responsibility 职责链模式(行为型模式) 请求的发送者与接受者 某些对象请求的接受者可能有多种多样,变化无常…… 动机(Motivation) 在软件构建过程中,一个请 ...

  2. 设计模式学习笔记——Chain of Responsibility职责链模式

    重点在链.一条链,如果本节点处理不了,则传递给下一个节点处理. 关键是如何传给下一个节点? 主要是由本节点决定传给哪一个节点. public class Client { public static ...

  3. Java设计模式(二十一):职责链模式

    职责链模式(Chain Of Responsibility Pattern) 职责链模式(Chain Of Responsibility Pattern):属于对象的行为模式.使多个对象都有机会处理请 ...

  4. 设计模式(二十四)——职责链模式(SpringMVC源码分析)

    1 学校 OA 系统的采购审批项目:需求是 采购员采购教学器材 1) 如果金额 小于等于 5000,  由教学主任审批 (0<=x<=5000) 2) 如果金额 小于等于 10000,   ...

  5. [Python设计模式] 第24章 加薪审批——职责链模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下情景 员工向经理发起加薪申请,经理无权决定,需要向总监汇报, ...

  6. python 设计模式之 (Chain of Responsibility)责任链模式

    #写在前面 对于每一种设计模式,如果不理解它的原理和结构,是写不出例子来的.所以弄明白很重要. 等过完这段浑浑噩噩的日子,我要找个遍地开花的地方开怀大笑一场 #责任链模式定义 简书上一网友就把这个定义 ...

  7. 设计模式(一)Chain Of Responsibility责任链模式

    设计模式篇章,源于网课的学习,以及个人的整理 在我们接收用户提交的字符时,常常会使用到过滤,在学习责任链模式前,我们是这样做的 1.定义一个类 public class MsgProcesser { ...

  8. 设计模式(13)--Chain of Responsibility(责任链模式)--行为型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一 ...

  9. 设计模式C++学习笔记之十七(Chain of Responsibility责任链模式)

      17.1.解释 概念:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. main(),客户 IWom ...

  10. go语言设计模式之Chain Of Responsibility(责任链)

    ChainOfResponsibility.go package ChainOfResponsibility import ( "fmt" "io" " ...

随机推荐

  1. Egret Wing3 商城插件下载和使用

    吐槽下官网目前找不到插件商城入口 . 根据管理员提供的地址: http://store.egret.com/work/21-0.html 平时我们可以在wing里直接打开商城. 打开wing使用向导 ...

  2. CentOS 6.5下搭建LAMP环境详细步骤

    1.确认搭建LAMP所需的环境是否已经安装: [root@localhost ~]#rpm -q make gcc gcc-c++ zlib-devel libtool libtool-ltdl li ...

  3. MySQL_关于用嵌套表计算的可以不用 20161205

    计算求和类的指标,其实用不到嵌套表,比如计算各城市产品分类的订单额. 如果要计算不重复的指标 比如一个用户一天下了多个订单 用这样的表计算一天有多少用户下单 这个用户肯定是去重的 下多个订单也应该视为 ...

  4. 最小生成树(HDOJ 1863)

    畅通工程 http://acm.hdu.edu.cn/showproblem.php?pid=1863 1.Prim算法: Prim算法是由一个点(最初的集合)向外延伸,找到与集合相连权值最小的边, ...

  5. css部分的复习

    常见的块元素有<h1><h6>.<p><div><ul><li><ol>等,其中<div>标记是最典型的 ...

  6. noip2006 2^k进制数

    设r是个2k进制数,并满足以下条件: (1)r至少是个2位的2k进制数. (2)作为2k进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进制数q后,则q的总位数不超过w ...

  7. for 循环

    #include <iostream> int main(){ ; ; val <= ; ++val) { sum += val; } std::cout << &quo ...

  8. 百思不得骑姐的问题——难道是控件的bug?

    直接进入主题,困惑了一下午了. 要实现的功能: winform的checkedlistbox控件 点击  “全部”  就都选上,可是如果点击过快就会出现如上现象,下面选项未显示选中. 代码如下: pr ...

  9. 关于Android中混淆的问题

    1.签名打包后库依赖报错,提示找不到依赖库的方法. 原因:混淆,依赖库的方法被混淆了. 解决方法:过滤混淆,即不要混淆这依赖库的文件. -keep class de.greenrobot.event. ...

  10. ASP.NET 创建网站地图

    很多个人站长会使用工具来生成自己网站的站点地图,这样做的缺点在于网站的 sitemap 不能及时的得到更新.当我们发表了一篇新文章时,应该对网站的地图进行更新,并通知搜索引擎网站地图已经发生了改变! ...