iOS 设计模式的应用 ⑮ 责任链

前言

    如果将很多人的智慧连接成一个链条,每个人都有自己的专长,联合起来就能形成强大的实体,这很像团队成员之间的合作。智慧链条中的每个单元都可以为问题的解决作出贡献。如果一个人不知道如何解决问题,他就会把问题沿着链条向下传,有的时候,即使有人知道如何解决,依旧会把问题传递下去,这样就能完成解决问题的特定过程。

    这种概念对于面向对象的软件设计同样适用,称为责任链模式。比如,让一组对象处理特定的请求,而对这个组添加或删除处理程序都不应影响组的完成性。

什么是责任链模式

   顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链,其避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

责任链模式的类图.png

    Handler 是上传抽象类,定义了一个方法 handlerRequest,处理它知道如何处理的请求对象。ConcreteHandler1ConcreteHandler2 实现了 handlerRequest 来处理它们认识的请求对象。 Handler 也有一个指向另一个同类实例 successor 的引用。当调用 Handler 实例的 handlerRequest 消息不知道如何处理请求时,会用同样的消息发送给 successor

什么时候使用责任链模式

  • 有多个对象可以处理请求,而处理程序只有在运行时才能确定;
  • 向一组对象发出请求,而不想显式指定请求的特定处理程序;

责任链模式的优缺点

责任链模式的优点

  1. 降低耦合度。它将请求的发送者和接收者解耦。
  2. 简化了对象。使得对象不需要知道链的结构。
  3. 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  4. 增加新的请求处理类很方便。

责任链模式的缺点

  1. 不能保证请求一定被接收。
  2. 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
  3. 可能不容易观察运行时的特征,有碍于除错。

责任链模式的实现

创建抽象类 AbstractLogger,带有详细的日志记录级别。

typedef enum : NSUInteger {
    Info,
    Debug,
    Error,
} LogLevel;

@interface AbstractLogger : NSObject

- (instancetype)initWithLevel:(LogLevel)level;

@property (nonatomic, assign) LogLevel level;

@property (nonatomic, strong) AbstractLogger *nextLogger;

- (void)logMessage:(NSString *)message Level:(LogLevel)level;


- (void)write:(NSString *)message;

@end
@implementation AbstractLogger

- (instancetype)initWithLevel:(LogLevel)level{
    self = [super init];
    if (self) {
        self.level = level;
    }
    return self;
}

- (void)logMessage:(NSString *)message Level:(LogLevel)level{
    if (level == self.level) {
        [self write:message];
    }
    if (self.nextLogger) {
        [self.nextLogger logMessage:message Level:level];
    }
}


- (void)write:(NSString *)message{
    
}

@end

然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。

@interface ConsoleLogger : AbstractLogger

@end
@implementation ConsoleLogger
  
- (void)write:(NSString *)message{
    NSLog(@"Console Logger %@",message);
}

@end
@interface FileLogger : AbstractLogger

@end
@implementation FileLogger

- (void)write:(NSString *)message{
    NSLog(@"File Logger %@",message);
}

@end
@interface ErrorLogger : AbstractLogger

@end
@implementation ErrorLogger
- (void)write:(NSString *)message{
    NSLog(@"Error Logger %@",message);
}

@end

向响应链发送请求

- (void)logMessage{
    AbstractLogger *loggerChain = [self getChainOfLoggers];
    
    [loggerChain logMessage:@"information" Level:Info];
    
    [loggerChain logMessage:@"debug" Level:Debug];

    [loggerChain logMessage:@"error" Level:Error];
}

- (AbstractLogger *)getChainOfLoggers{
    ErrorLogger *errorLogger = [[ErrorLogger alloc] initWithLevel:Error];
    FileLogger *fileLogger = [[FileLogger alloc] initWithLevel:Debug];
    ConsoleLogger *consoleLogger = [[ConsoleLogger alloc] initWithLevel:Info];
    
    [errorLogger setNextLogger:fileLogger];
    [fileLogger setNextLogger:consoleLogger];
    return  errorLogger;
}

Cocoa 中的责任链模式

    应用程序框架包括一个称为响应者链的架构。该链由一系列响应者对象(继承自UIResponder) 事件(例如,鼠标单击)或操作消息被传递并(通常)最终被处理。如果给定的响应者对象不处理特定消息,它会将消息传递给链中的下一个响应者。响应者对象在链中的顺序通常由视图层次结构决定,在层次结构中从较低级别到较高级别的响应者,如果视图由UIViewController对象管理,则视图控制器将成为链中的下一个响应者(事件或操作消息从那里传递到视图的父视图)。响应者链上的事件和动作消息的路径是不同的。

总结

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 抽象工厂 抽象工厂模式提供了一个接口,用于创建相关或依赖对象的族,而不指定具体的类。 客户与从工厂获得的具体对象的...
    woshishui1243阅读 3,389评论 1 5
  • 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计...
    酷拼车阅读 348评论 0 0
  • 原创:知识点总结性文章创作不易,请珍惜,之后会持续更新,不断完善个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈...
    时光啊混蛋_97boy阅读 281评论 0 6
  • 在软件工程中,(引自维基百科)设计模式[https://zh.wikipedia.org/wiki/%E8%AE%...
    jackyshan阅读 39,920评论 7 204
  • 责任链设计模式及其典型应用场景剖析 前言 责任链模式作为行为型设计模式的重要组成部分,在 Android 开发中有...
    allen218阅读 5,189评论 0 0