责任链模式

定义

为了避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止,职责链模式又称为责任链模式,它是一种对象行为型模式。(如果你接触过异常处理,那么套用异常处理机制可以更好地理解)。

职责链可以是一条直线,也可以是一个环,还可以是一个树形结构,不过最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传递,由链上的处理者对请求进行相应的处理,而客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,通过这种方法将请求的发送者和请求的处理者解耦,消除两个角色间的依赖关系,可以自由地组合。

原理结构

上图阐释的是职责连模式的实现原理,主要角色包括:

Handler:抽象处理者。定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。

ConcreteHandler: 具体处理者。具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

Client:客户端

handleRequest:抽象处理者的公用接口,要求每个链式节点都实现这个接口,能够处理客户端发过来的请求数据。

对于每个链式节点,需要满足一下两个条件:

实现抽象处理者(Handler)所定义的抽象接口,能够识别接收的请求;

有一个successor,用于把当前不能处理的请求转发传递到下一个节点,如此才能形成一个链。(successor是指下一个ConcreteHandler的引用,相当于链表里面的next指针)

由于通过上述的编程设计,使得请求和处理该请求的对象完全没有依赖关系,因为客户端甚至不知道是谁处理了这个请求,这样的话,使得整个链式结构很灵活,可以随时添加新的的节点,当然也支持随意调节节点顺序、删除不必要的节点等等操作。

iOS实现

职责链模式的一个很重要的特点是,当客户发出请求之后,客户端并不知道哪一个对象最终处理这个请求,这样系统的更改可以在不影响客户端的情况下动态地重新组织和分配责任。

下面给出类结构图。

从上图可以看出,当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。这样做的好处是请求者不用管哪个对象来处理,反正最终是要被某一个对象处理就是了。也就是说接收者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。

这些特点的好处是我们可以随时增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。但是,一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理,所以这更需要我们事先考虑全面。

好的,说了这么多,还是老样子,给大家展示一下简单的示意代码。

注意:本文所有代码均在ARC环境下编译通过。

Handlers类接口

复制代码代码如下:

#import

@interface Handlers :NSObject{

Handlers *mySuccessor;

}

-(void)SetSuccessor:(Handlers*)successor;

-(void)HandleRequest:(int)request;

@end

Handlers类实现

复制代码代码如下:

#import "Handlers.h"

@implementation Handlers

-(void)SetSuccessor:(Handlers *)successor{

mySuccessor = successor;

}

-(void)HandleRequest:(int)request{

return;

}

@end

ConcreteHandler1类接口

复制代码代码如下:

#import "Handlers.h"

@interface ConcreteHandler1:Handlers

-(void)HandleRequest:(int)request;

@end

ConcreteHandler1类实现

#import "ConcreteHandler1.h"

@implementation ConcreteHandler1

-(void)HandleRequest:(int)request{

if (request >=0 && request <10) {

NSLog(@"ConcreteHandler1处理%d", request);

}

else if (mySuccessor !=nil) {

[mySuccessor HandleRequest:request];

}

}

@end

ConcreteHandler2类接口

复制代码代码如下:

#import "Handlers.h"

@interface ConcreteHandler2 :Handlers

@end

ConcreteHandler2类实现

复制代码代码如下:

#import "ConcreteHandler2.h"

@implementation ConcreteHandler2

-(void)HandleRequest:(int)request{

if (request >=10 && request <20) {

NSLog(@"ConcreteHandler2处理%d", request);

}

else if(mySuccessor !=nil) {

[mySuccessor HandleRequest:request];

}

}

@end

ConcreteHandler3类接口

复制代码代码如下:

#import "Handlers.h"

@interface ConcreteHandler3 :Handlers

@end

ConcreteHandler3类实现

复制代码代码如下:

#import "ConcreteHandler3.h"

@implementation ConcreteHandler3

-(void)HandleRequest:(int)request{

if (request >=20 && request <30) {

NSLog(@"ConcreteHandler3处理%d", request);

}

else if (mySuccessor !=nil) {

[mySuccessor HandleRequest:request];

}

}

@end

Main方法调用

复制代码代码如下:

#import

int main(int argc,const char * argv[])

{

@autoreleasepool{

Handlers *h1 = [[ConcreteHandler1 alloc]init];

Handlers *h2 = [[ConcreteHandler2 alloc]init];

Handlers *h3 = [[ConcreteHandler3 alloc]init];

[h1 SetSuccessor:h2];

[h2 SetSuccessor:h3];

int requests[] = {2,5,14,22,18,3,27,20};

for (int i =0; i <8; i++) {

[h1 HandleRequest:requests[i]];

}

}

return 0;

}

好啦,代码展示完毕!收工!

小结

行为型模式是对在不同的对象之间划分责任和算法的抽象化,行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。行为型模式可以分为类行为型模式和对象行为型模式两种。职责链模式可以避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止,它是一种对象行为型模式。

在我们日常使用中,我们或许直接接触这方面的机会不多,但是,如果你认真有研究过程序的一场处理机制,那么你就能够发现这种处理机制正是采用职责链的方式处理程序中抛出的异常错误的。

在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

职责链模式的主要优点在于可以降低系统的耦合度,简化对象的相互连接,同时增强给对象指派职责的灵活性,增加新的请求处理类也很方便;其主要缺点在于不能保证请求一定被接收,且对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。

优点:

降低耦合度。

可简化对象的相互连接。

增强给对象指派职责的灵活性。

增加新的请求处理类很方便。

缺点:

不能保证请求一定被接收。

系统性能将受到一定影响,而且在进行代码调试时不太方便(可能会造成循环调用)。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,820评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,648评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,324评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,714评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,724评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,328评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,897评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,804评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,345评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,431评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,561评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,238评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,928评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,417评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,528评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,983评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,573评论 2 359

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 申请聚餐费用## 来考虑这样一个功能:申请聚餐费用的管理。 很多公司都有这样的福利,就是项...
    七寸知架构阅读 3,147评论 3 58
  • 源码地址 介绍 它是一种行为型设计模式之一。它的每一个节点都可以看作是一个对象,每一个对象拥有不同的处理逻辑,将一...
    yangMr阅读 733评论 0 3
  • 目录 本文的结构如下: 引言 什么是责任链模式 模式的结构 典型代码 代码示例 纯与不纯的责任链模式 优点和缺点 ...
    w1992wishes阅读 1,260评论 4 14
  • 被别人问到,自己只知道这个名字,但是完全不知道内容,竟然还是这么常用的设计的模式,丢人啊,然后找到一篇,介绍简单好...
    壹人城阅读 1,151评论 0 7
  • 对我而言,你是我信仰一般的存在,我不知为什么说出这样的话,可能天性使然吧!你那样平凡,在我看来并没有什么优点可言...
    你的名字Y我的故事阅读 176评论 0 0