定义
很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
解决场景
职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
如何使用
在处理消息的时候以过滤很多道。
应用实例举例
1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
使用场景
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
优缺点
优点
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
实现方式:
1、链表方式:比如刚才的请假审批
2、非链表方式:通过集合,数组生成责任链更加实用,将链表上的各个对象都添加到集合中,然后通过反射给构建出来。
场景模拟
打印不同等级的log
职责链UML 图
简单代码
@interface AbstractLogger : NSObject
@property (nonatomic,assign) int level;
@property (nonatomic,strong) AbstractLogger *nextLogger;
- (instancetype)initWithLevel:(int)level;
-(void)writeLog:(NSString *)message;
-(void)printLog:(int)level message:(NSString*)message;
@end
#import "AbstractLogger.h"
@implementation AbstractLogger
- (instancetype)initWithLevel:(int)level
{
self = [super init];
if (self) {
self.level = level;
}
return self;
}
-(void)printLog:(int)level message:(NSString *)message
{
if (self.level<=level) {
[self writeLog:message];
}
if (self.nextLogger) {
[self.nextLogger printLog:level message:message];
}
}
@end
#import "AbstractLogger.h"
@interface ConsloleLogger : AbstractLogger
@end
#import "ConsloleLogger.h"
@implementation ConsloleLogger
-(void)writeLog:(NSString *)message
{
NSLog(@"Standard Console::Logger: %@",message);
}
@end
#import "AbstractLogger.h"
@interface DebugLogger : AbstractLogger
@end
#import "DebugLogger.h"
@implementation DebugLogger
-(void)writeLog:(NSString *)message
{
NSLog(@"Debug Console::Logger: %@",message);
}
@end
#import "AbstractLogger.h"
@interface ErrorLogger : AbstractLogger
@end
#import "ErrorLogger.h"
@implementation ErrorLogger
-(void)writeLog:(NSString *)message
{
NSLog(@"Error Console::Logger: %@",message);
}
@end
测试代码
- (void)viewDidLoad {
[super viewDidLoad];
AbstractLogger * logger = [[ConsloleLogger alloc]initWithLevel:1];
AbstractLogger * logger2 = [[DebugLogger alloc]initWithLevel:2];
AbstractLogger * logger3 = [[ErrorLogger alloc]initWithLevel:3];
logger.nextLogger= logger2;
logger2.nextLogger = logger3;
[logger printLog:2 message:@"天天向上"];
[logger printLog:1 message:@"没有错误"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
测试结果
2018-04-10 11:10:48.467237+0800 行为型设计模式-职责链模式[49779:8034730] Standard Console::Logger: 天天向上
2018-04-10 11:10:48.467380+0800 行为型设计模式-职责链模式[49779:8034730] Debug Console::Logger: 天天向上
2018-04-10 11:10:48.467477+0800 行为型设计模式-职责链模式[49779:8034730] Standard Console::Logger: 没有错误
这里我们把AbstractLogger 当做接口使用。
总结
上面的例子是责任链没有顺序的,只要是连接起来就行了。
有时候我们需要将责任链按照一定顺序连接起来,(ios 的响应链),这样的好处就是我们按照顺序来处理事件了,要是有响应者了处理该事件了,可以接着传递下去也可以就终止了。
源代码地址
下一篇博客
行为型设计模式-命令模式