iOS设计模式--责任链模式

何为责任链模式?

责任链模式的主要思想是,对象引用了同一类型的另一个对象,形成一条链。链中的每个对象实现了同样的方法,处理对链中第一个对象发起的同一个请求。如果一个对象不知道如何处理请求,它就把请求传递给下一个响应者。

责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间发生耦合。此模式将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

何时使用责任链模式?

@:有多个对象可以处理请求,而处理程序只有在运行时才能确定。

@:向一组对象发出请求,而不想显示指定处理请求的特定处理程序。

在游戏中使用责任链模式

假定我们要开发一款游戏,里面的每个人物都可以通过做任务赚取点数来升级防御道具。防御道具可以使盾牌或者盔甲。每种形式的防御只能应付一种特定的攻击,如果防御道具不认识一种进攻,它就把进攻的作用传递给下一个会响应它的实体。比如,盔甲1不知道如何对付对手的攻击,所以把它传给下一个盔甲,盔甲2。盔甲2刚好知道如何对付这次攻击,化解了人物可能受到的损伤。由于某种原因,如果没有盔甲可以对这次攻击做出响应,攻击的作用最终会传到人物。人物对攻击做出响应时,会表现为一定程度的损伤。

这种只让每个独立的防御道具对特定类型的攻击做出相应的机制,简化了人物使用各种防御道具的复杂性。每种盔甲各自负责非常特定的功能。这就是责任链模式的作用所在。

下面我们将使用责任链模式实现这个设计,假设有两种防御:水盔甲和火盔甲。它们都只能按照设计对付某些攻击。水盔甲可以防御来自水的攻击,火盔甲可以防御来自火的攻击。人物也是响应链的一部分,因此它也应该跟其他防御道具具有共同的行为,对攻击做出响应。

WaterAttackHandler、FireAttackHandler和Avatar是AttackHandler的子类。AttackHandler定义了一个方法——handleAttack:attack,该方法的默认行为是,把攻击传给另一个AttackHandler的引用,即成员变量nextAttackHandler。子类重载这个方法,对攻击提供实际的响应。如果AttackHandler不知道如何响应一个攻击,那么就使用[super handleAttack:attack];消息,把它转发给super,这样super的默认实现就会把攻击沿着链给传下去。

定义3中类型的攻击,WaterAttack、FireAttack、SoliderAttack。先看下AttackHandler父类的代码,代码如下:

#import <Foundation/Foundation.h>
#import "Attack.h"
@interface AttackHandler : NSObject

@property (nonatomic, strong) AttackHandler *nextAttackHandler;

- (void)handleAttack:(Attack *)attack;

@end

AttackHandler定义了一个同类型的私有变量nextAttackHandler,它是攻击的下一个响应者。AttackHander的子类应该重载handleAttack:方法,以响应它能够识别的一种攻击。抽象的AttackHandler为这个方法定义了默认行为,代码如下:

#import "AttackHandler.h"

@implementation AttackHandler

- (void)handleAttack:(Attack *)attack {
    // 默认调用nextAttackHandler进行处理。
    [_nextAttackHandler handleAttack:attack];
}

@end

如果子类没有重载这个方法,默认的handleAttack:实现就会被调用。这个方法只是把攻击传给nextAttackHandler去处理。

接下来看下任务的第一个防御道具WaterAttackHandler,WaterAttackHandler子类化AttackHandler并重载其handleAttack:方法,代码如下:

#import "AttackHandler.h"

@interface WaterAttackHandler : AttackHandler

// 重写处理攻击方法
- (void)handleAttack:(Attack *)attack;

@end

在.h中再次声明重载的方法不是必需的,但是这样做更加清晰。WaterAttackHandler只能识别WaterAttack的实例,如果攻击确实是WaterAttack类型,那么handleAttack:将用NSLog输出@"我挡下了水的攻击";否则,它输出另一条消息并使用[super handleAttack:attack];把攻击转给super,代码如下:

#import "WaterAttackHandler.h"
#import "WaterAttack.h"
@implementation WaterAttackHandler

- (void)handleAttack:(Attack *)attack {
    if ([attack isKindOfClass:[WaterAttack class]]) {
        NSLog(@"我挡下了水的攻击");
    }else {
        NSLog(@"我处理不了来自%@的攻击", [attack class]);
        [super handleAttack:attack];
    }
}

@end

类似的FireAttackHandler也是同样的道理,代码如下:

#import "AttackHandler.h"

@interface FireAttackHandler : AttackHandler

// 重写处理攻击的方法
- (void)handleAttack:(Attack *)attack;

@end
#import "FireAttackHandler.h"
#import "FireAttack.h"
@implementation FireAttackHandler

- (void)handleAttack:(Attack *)attack {
    if ([attack isKindOfClass:[FireAttack class]]) {
        NSLog(@"我挡下了火的攻击");
    }else {
        NSLog(@"我处理不了来自%@的攻击", [attack class]);
        [super handleAttack:attack];
    }
}

@end

如果没有防具能够对付攻击,攻击最终将传给Avatar(游戏人物)。Avatar也是AttackHandler的子类,而且与WaterAttackHandler、FireAttackHandler有相同的响应机制。但是,攻击到这里的时候,Avatar将没有防御而受到损伤。将会输出NSLog(@"我被%@攻击到了", [attack class]);,输出攻击的名称。代码如下:

#import "AttackHandler.h"

@interface Avatar : AttackHandler

- (void)handleAttack:(Attack *)attack;

@end
#import "Avatar.h"

@implementation Avatar

- (void)handleAttack:(Attack *)attack {
    NSLog(@"我被%@攻击到了", [attack class]);
}

@end

现在已经定义好了所有的AttackHandler。来看下客户端代码,看看下责任链模式的使用,客户端代码如下:

#import "ViewController.h"
#import "Attack.h"
#import "WaterAttack.h"
#import "FireAttack.h"
#import "SoliderAttack.h"
#import "AttackHandler.h"
#import "WaterAttackHandler.h"
#import "FireAttackHandler.h"
#import "Avatar.h"
@interface ViewController ()

@end

@implementation ViewController

#pragma mark - life cycle

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建一个游戏人物
    AttackHandler *avatar = [[Avatar alloc] init];
    
    // 给其穿上防水的铠甲
    AttackHandler *waterAramedAvatar = [[WaterAttackHandler alloc] init];
    [waterAramedAvatar setNextAttackHandler:avatar];
    
    // 然后在穿上防火的铠甲
    AttackHandler *fireAramedAvatar = [[FireAttackHandler alloc] init];
    [fireAramedAvatar setNextAttackHandler:waterAramedAvatar];
    
    // ....以后还可以加其他行动
    
    // 用用水攻击游戏人物
    Attack *waterAttack = [[WaterAttack alloc] init];
    [fireAramedAvatar handleAttack:waterAttack];
    
    // 用火攻击游戏人物
    Attack *fireAttack = [[FireAttack alloc] init];
    [fireAramedAvatar handleAttack:fireAttack];
    
    // 用土攻击游戏人物
    Attack *soliderAttack = [[SoliderAttack alloc] init];
    [fireAramedAvatar handleAttack:soliderAttack];
    
    // ....以后可以加其他的攻击
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

这个攻击有点像栈(先进后出)。因为需要让Avatar是攻击的最后一站,所以它要最先创建。然后创WaterAttackHandler的实例,把Avatar作为它的下一个AttackHandler。它们被当做增强了Avatar,WaterAttackHandler是它通往真正Avatar实例的第一道门。然后,添加FireAttackHandler作为Avatar的另一种防御。此时,Avatar已经具有两种防御道具了。

在游戏中的某个时刻,我们创建了3中类型的攻击——waterAttack、fireAttack、soliderAttack,调用handleAttack:方法去处理,以下是来自责任链中各种AttackHandler的输出,客户端输出如下:

2015-08-21 14:57:31.922 ChainResponsibilityDemo[25726:1690159] 我处理不了来自WaterAttack的攻击
2015-08-21 14:57:31.923 ChainResponsibilityDemo[25726:1690159] 我挡下了水的攻击
2015-08-21 14:57:31.923 ChainResponsibilityDemo[25726:1690159] 我挡下了火的攻击
2015-08-21 14:57:31.923 ChainResponsibilityDemo[25726:1690159] 我处理不了来自SoliderAttack的攻击
2015-08-21 14:57:31.923 ChainResponsibilityDemo[25726:1690159] 我处理不了来自SoliderAttack的攻击
2015-08-21 14:57:31.924 ChainResponsibilityDemo[25726:1690159] 我被SoliderAttack攻击到了

这个例子演示了如何使用责任链模式,来简化人物处理各种攻击的编码和逻辑。如果不用这个模式,防御逻辑很可能都塞到一个类中(比如Avatar),代码会乱成一团的。

demo地址:

https://github.com/guoshimeihua/ChainResponsibilityDemo

时间: 2024-10-12 08:37:21

iOS设计模式--责任链模式的相关文章

java 设计模式 -- 责任链模式

设计模式 – 责任链模式 介绍: 责任链模式是一种动态行为模式,有多个对象,每一个对象分别拥有其下家的引用.连起来形成一条链.待处理对象则传到此链上,在此链进行传递,且待处理对象并不知道此会被链上的哪个对象处理,这使得我们能够动态的添加链上的对象而且分配责任. 纯责任链和非纯责任链 责任链分为两种.纯责任链和非纯责任链. 纯责任链是待处理对象request在处理对象handler链上传递,每一个处理对象handler处理request的一部分,到终于处理完毕.非纯责任链则是待处理对象reques

[设计模式] 责任链模式之变种 - 责任链子

今天看到 wikipedia 的责任链模式,好奇之下搜寻相关文章,此文章主要参考 91大的 [.NET]重构之路系列v11 –用责任链模式打破讨厌的switch case 的变种作法,所以跟原本的责任链模式的设计思路不太相同,但结果相同, 所以阅读前,建议先看完91大的文章后,在来看这篇会比较能感觉出差异. ?这边先引用91大文章结尾结论中的补充来复习一下责任链的重点, 20120415 补充:责任链的用意在于把每个角色的职责分清楚,每个对象只需要做好自己的事,透过责任链的方式来组合,并完成使用

24天学会设计模式------责任链模式

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka/article/details/43210027 一.责任链模式(Chain of Responsibility Pattern) 1.简介 从名字上大概也能猜出这个模式的大概模样--系统中将会存在多个有类似处理能力的对象.当一个请求触发后,请求将在这些对象组成的链条中传递,直到找到最合适的"责任"对象,并进行处理.<设计模式>中给它的定义如下:使多个对象都有机会处理请

Java与设计模式-责任链模式

责任链模式属于行为型设计模式之一,怎么理解责任链?责任链是可以理解成数个对象首尾连接而成,每一个节点就是一个对象,每个对象对应不同的处理逻辑,直至有一个对象响应处理请求结束.这一种模式成为责任链模式. 生活中可以找到责任链模式的原型吗?这种例子很多,比如你要去买房子,首先是销售人员(对象1)接待你,你说想要百分之3的折扣,没问题,这时销售人员就有打百分之三折扣的权限,销售人员(对象1)进行处理.这时来了一个土豪,说要买10套,要百分之五的折扣,销售人员(对象1)没有百分之五折扣的权限,必须要想上

我的Java设计模式-责任链模式

今天来说说程序员小猿和产品就关于需求发生的故事.前不久,小猿收到了产品的需求. 产品经理:小猿,为了迎合大众屌丝用户的口味,我们要放一张图,要露点的. 小猿:......露点?你大爷的,让身为正义与纯洁化身的我做这种需求,还露点. 产品经理:误会误会,是放一张暴露一点点的,尺寸不大. 小猿:尼玛~能说清楚些吗,需求模棱两可的.不干,我要上报boss. 产品经理也一阵无语,这豆丁的事还上报boss.话说这上报也得走程序是吧,技术经理就不干了,"凭什么要跳过我,得经过我才能到boss".咦

设计模式-责任链模式在实际项目中的使用

最近一次迭代,参与了公司数据应用平台的开发,其中负责的一块功能早早的就完成了代码的编写工作,即将进入测试阶段,因为有时间思考和总结代码编写中遇到的难题,便想着将代码做一次重构:其中优化的一个功能就是关于数据平台敏感字段的收集 功能描述:数据平台敏感字段的收集: 提供 service 方法,查询是否需要扫描表做触发式收集,指定具体实例与库的表,随机取 N 行(1~max(id) 之间):a.对每一行的每一个字段的值(取非 null 非空的值)做正则匹配 b. 对每一行的每一个字段的值看是否包含了敏

iOS设计模式 - 责任链

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

24种设计模式--责任链模式【Chain ofResponsibility Pattern】

中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父.既嫁从夫.夫死从子”,也就是说一个女性,在没有结婚的时候要听从于父亲,结了婚后听从于丈夫,丈夫死了还要听儿子的,举个例子来说,一个女的要出去逛街,同样这样的一个请求,在她没有出嫁前她必须征得父亲的同意,出嫁之后必须获得丈夫的许可,那丈夫死了怎么办?一般都是男的比女的死的早,还要问问儿子是否允许自己出去逛街,估计你下边马上要问要是没有儿子怎么办?请示小叔子.侄子等等,在父系社会中,妇女只占从属地位,现在想想中国的妇女还是比较悲惨的

设计模式 -- 责任链模式或者叫职责链模式(Chain of Responsibility(CoR))

什么是链?前后相连,一个连接下一个,其中包括多个节点,其实责任链模式也类似,他是多个对象之间相互关联,下一个对象的操作由上一个对象关联下来,上一个对象有个方法用于指向其他对象.职责链之间的前后关系是可以改变的,主要看上一节点主要指向哪个节点. android中事件分发就是责任链模式的具体表现: View的ontouchEvent返回值设置,如果为true,交个自己的消费事件的方法去处理,如果为false,则继续向下一个进行传递. 如何实现责任链模式: 比如责任链上有,A,B,C三个对象,如果A有