責任鏈模式在 iOS 中的應用
阿新 • • 發佈:2019-01-05
名稱
責任鏈模式 Chain of Responsibility Pattren
用途
- 解耦訊息的傳送者和接受者。
- 讓多個物件有機會處理某個請求(UI 響應鏈、Planck 中介軟體、流式業務流程(OA)、過濾器)。
實現
- 為某個請求建立一個物件鏈,每個物件依次檢查次請求並對其進行處理,或者將它傳遞給鏈中的下一個物件。
- 鏈的實現:使用現成的鏈(如繼承關係)或自己實現新鏈(next指標)
- 鏈上的每個物件都採用同樣的介面處理或上拋事件
優點
- 解耦請求的傳送者和接收者
- 簡化物件(不關心鏈結構)
- 鏈內成員可以靈活增刪調序
缺點
- 不保證請求一定被處理
- 靈活的長鏈可能給 Debug 增加複雜度
Cocoa 中的應用
- Responder Chain 使得互動事件可以通過連結串列依次傳遞來被處理(或忽略)訊息。
- 與使用者互動的物件(如Application, Window, View, ViewController)都是 NSResponder/UIResponder 的子類。
- 首先確定 first responder (觸控事件採用 Hit-Test),隨後 responder 決定是否處理事件或通過 nextResponder 繼續傳遞。
- 這個響應鏈大部分情況下是 View 的繼承鏈,Root UIView 的 next responder 是 UIViewController,VC 的下一個是 UIWindow,最後是 UIApplocation 的 delegate 且為 UIResponder 的子類;當然也可以通過 setNextResponder: 來改變它。
自己動手實現(Objective-C Code)
1. Array 在外部維護鏈
YFHandler
@interface YFHandler : NSObject
@property (assign, nonatomic, readwrite) NSUInteger index;
- (BOOL)handleBusiness:(NSUInteger)index;
@end
@implementation YFHandler
- (BOOL)handleBusiness:(NSUInteger)businessIndex {
if (self.index == businessIndex) {
// Business Logic Here
NSLog(@"business %@ has been handled with handler %@", @(businessIndex), @(self.index));
return YES;
} else {
return NO;
}
}
@end
YFHandlerManager
@class YFHandler;
@interface YFHandlerManager : NSObject
- (void)addHandlerCount:(NSUInteger)count;
- (void)handleBusiness:(NSUInteger)businessIndex;
@end
@interface YFHandlerManager ()
@property (nonatomic, strong, readwrite) NSMutableArray<YFHandler *> *handlers;
@end
@implementation YFHandlerManager
- (instancetype)init {
self = [super init];
if (self) {
self.handlers = [NSMutableArray array];
}
return self;
}
- (void)addHandlerCount:(NSUInteger)count {
for (NSUInteger i = 1; i <= count; i++) {
YFHandler *handler = [[YFHandler alloc] init];
handler.index = i;
[self.handlers addObject:handler];
}
}
- (void)handleBusiness:(NSUInteger)businessIndex {
[self.handlers enumerateObjectsUsingBlock:^(YFHandler * _Nonnull handler, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL handled = [handler handleBusiness:businessIndex];
*stop = handled;
BOOL isLastHandler = (idx == self.handlers.count - 1);
if (isLastHandler && !handled) {
NSLog(@"No handler is capable of handling businsess %@", @(businessIndex));
}
}];
}
Usage
- (void)handleBusinessOnArrayChain {
YFHandlerManager *manager = [[YFHandlerManager alloc] init];
[manager addHandlerCount:10];
[manager handleBusiness:11];
}
2. Handler 自身維護鏈
YFHandlerWithNextPoint
@interface YFHandlerWithNextPoint : NSObject
@property (assign, nonatomic, readwrite) NSUInteger index;
@property (nonatomic, strong, readwrite) YFHandlerWithNextPoint *nextHander;
- (void)handleBusiness:(NSUInteger)index;
@end
@implementation YFHandlerWithNextPoint
- (void)handleBusiness:(NSUInteger)businessIndex {
if (self.index == businessIndex) {
// Business Logic Here
NSLog(@"business %@ has been handled with handler %@", @(businessIndex), @(self.index));
} else {
[self.nextHander handleBusiness:businessIndex];
}
}
@end
Usage
- (void)handleBusinessOnOwnChain {
YFHandlerWithNextPoint *firstHandler = [self firstHandlerWithTotalCount:10];
[firstHandler handleBusiness:8];
}
- (YFHandlerWithNextPoint *)firstHandlerWithTotalCount:(NSUInteger)handlerCount {
YFHandlerWithNextPoint *firstHandler = nil;
YFHandlerWithNextPoint *lastHandler = nil;
for (NSUInteger i = 1; i <= handlerCount; i++) {
YFHandlerWithNextPoint *thisHandler = [[YFHandlerWithNextPoint alloc] init];
thisHandler.index = i;
if (i == 1) {
firstHandler = thisHandler;
} else {
lastHandler.nextHander = thisHandler;
}
lastHandler = thisHandler;
}
return firstHandler;
}