索引

意图

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

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

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. Repeater控件 ---属性(ItemCommand事件)

    epeater的Command操作:1.ItemCommand事件 - 在Repeater中所有能触发事件的控件,都会来触发这一个事件 2.CommandName - 判断点击的是什么按钮,e.Com ...

  2. IconFont字体制作

    1. 第一步.准备svg格式图片 2. 登陆http://iconfont.cn/网站,上传图标. 3. 选中需要制作成iconfont的图标. 4. 将选中的图标转储为项目 5. 下载至本地. 6. ...

  3. win8自动升级win8.1后 wampserver无法启动

    原因是升级时win8把其他的系统服务都给停止了. 解决办法是左键点击wamp的小图标,选择apache/mysql - service - 安装服务. 然后再选择启动服务,即可.

  4. C++之jsoncpp学习

    最新由于客户端要用到jsoncpp,所以自己也跟着项目的需求学了一下jsoncpp.以前没用过xml,但是感觉接触json后,还蛮好用的. 参考地址 http://jsoncpp.sourceforg ...

  5. js onkeypress与onkeydown 事件区别详细说明

    keypress只适用于有字符输入的按键 而keyup/keydown包含了Ctrl, Shift之类的情况 Firefox在处理onKeyDown/onKeyPress事件时存在漏洞,恶意网页可能利 ...

  6. CSS BOX模型

    对于box模型概念的理解以及它与决定元素最终尺寸的方式有何关系,是理解如何设定网 页上的元素位置的基础.box模型应用到块级元素.一个随之而来的概念,内联布局模型 定义了如何设定内联元素的位置. 对于 ...

  7. Brn系列网上商城数据库说明文档

    单店版BrnShop_1.9.351数据字典:点击下载 多店版BrnMall_1.9.496数据字典:点击下载 有对网上商城程序设计感兴趣的朋友,欢迎加入QQ群:235274151,大家可以交流下!

  8. scala学习心得(2)

    scala类中可以通过override 重载方法 scala定义的函数式类不可被改变,这样传进去的参数就需要提前被检验,可以通过scala.predef包中的方法require方法 定义辅助构造器 d ...

  9. nyoj 737 石子合并(一)。区间dp

    http://acm.nyist.net/JudgeOnline/problem.php?pid=737 数据很小,适合区间dp的入门 对于第[i, j]堆,无论你怎么合并,无论你先选哪两堆结合,当你 ...

  10. android 编译错误 com/android/dx/command/dexer/Main : Unsupported major.minor version 52.0

    解决方案一: JDK版本不一致造成的,指的是高版本的JDK编译的class不能放在低版本的JDK上运行. 如果是Version 52,就表示JDK8编译的class不能运行在JDK7上,所以需要在本地 ...