当涉及到模块化和组件化开发时,中介者形式(Mediator Pattern)能够帮助解耦不同模块之间的依靠关系。它通过供给一个统一的接口,将模块之间的通讯和交互逻辑会集在一个中间件类中,而不是直接依靠于具体的模块。
中介者形式OC完结类
// YJHMediator.h
#import <Foundation/Foundation.h>
@interface YJHMediator : NSObject
+ (instancetype)sharedInstance;
// 长途App调用进口
- (id)performActionWithUrl:(NSURL *)url completion:(void(^)(NSDictionary *info))completion;
// 本地组件调用进口
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget;
- (void)releaseCachedTargetWithTargetName:(NSString *)targetName;
@end
#import "YJHMediator.h"
// 界说 YJHMediator 的私有接口
@interface YJHMediator ()
// 存储缓存的方针方针的字典
@property (nonatomic, strong) NSMutableDictionary *cachedTarget;
@end
// 完结 YJHMediator 类
@implementation YJHMediator
#pragma mark - public methods
// 单例办法,回来同享的 YJHMediator 实例
+ (instancetype)sharedInstance
{
static YJHMediator *mediator;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mediator = [[YJHMediator alloc] init];
});
return mediator;
}
/*
scheme://[target]/[action]?[params]
url sample:
aaa://targetA/actionB?id=1234
*/
// 依据 URL 履行对应的操作,并在完结时调用 completion 回调
- (id)performActionWithUrl:(NSURL *)url completion:(void (^)(NSDictionary *))completion
{
// 创立参数字典
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
// 获取 URL 的查询部分
NSString *urlString = [url query];
// 遍历查询部分,将参数解析为键值对并保存到 params 字典中
for (NSString *param in [urlString componentsSeparatedByString:@"&"]) {
NSArray *elts = [param componentsSeparatedByString:@"="];
if([elts count] < 2) continue;
[params setObject:[elts lastObject] forKey:[elts firstObject]];
}
// 依据 URL 的路径获取 actionName
NSString *actionName = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""];
// 查看 actionName 是否以 "native" 最初,假如是则回来 NO
if ([actionName hasPrefix:@"native"]) {
return @(NO);
}
// 调用 performTarget:action:params:shouldCacheTarget: 办法履行方针操作,并回来成果
id result = [self performTarget:url.host action:actionName params:params shouldCacheTarget:NO];
// 履行 completion 回调,并传递成果字典
if (completion) {
if (result) {
completion(@{@"result":result});
} else {
completion(nil);
}
}
// 回来成果
return result;
}
// 履行方针操作的办法
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget
{
// 查看 targetName 和 actionName 是否为空
if (!targetName || !actionName) {
return nil;
}
// 构造方针类名
NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
// 构造办法名
NSString *actionString = [NSString stringWithFormat:@"IMP_%@", actionName];
// 假如 params 不为空,将冒号添加到 actionString 后面
if (params != nil) {
actionString = [actionString stringByAppendingString:@":"];
}
id target = nil;
// 运用同步锁保证多线程安全
@synchronized (self) {
target = self.cachedTarget[targetClassString];
}
// 假如缓存中没有方针方针,则依据 targetClassString 创立方针方针
if (target == nil) {
Class targetClass = NSClassFromString(targetClassString);
target = [[targetClass alloc] init];
}
SEL action = NSSelectorFromString(actionString);
// 假如方针方针为空,直接回来空
if (target == nil) {
return nil;
}
// 假如 shouldCacheTarget 为 YES,则将方针方针缓存起来
if (shouldCacheTarget) {
@synchronized (self) {
self.cachedTarget[targetClassString] = target;
}
}
// 查看方针方针是否响应 action 办法,假如是,则履行安全的办法调用
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 假如方针方针不响应 action 办法,则尝试调用方针方针的 notFound: 办法进行统一处理
SEL action = NSSelectorFromString(@"notFound:");
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 假如方针方针也没有 notFound: 办法,则直接回来空
return nil;
}
}
}
// 安全的办法调用,防止因为办法签名不匹配导致的溃散
- (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params
{
NSMethodSignature *methodSignature = [target methodSignatureForSelector:action];
if (methodSignature == nil) {
return nil;
}
const char *retType = [methodSignature methodReturnType];
if (strcmp(retType, @encode(void)) == 0) {
// 回来值为 void 的办法调用
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setSelector:action];
[invocation setTarget:target];
if (params) {
[invocation setArgument:¶ms atIndex:2];
}
[invocation invoke];
return nil;
} else if (strcmp(retType, @encode(NSInteger)) == 0) {
// 回来值为 NSInteger 的办法调用
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setSelector:action];
[invocation setTarget:target];
if (params) {
[invocation setArgument:¶ms atIndex:2];
}
[invocation invoke];
NSInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
} else {
// 其他类型的回来值
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setSelector:action];
[invocation setTarget:target];
if (params) {
[invocation setArgument:¶ms atIndex:2];
}
[invocation invoke];
id result = nil;
[invocation getReturnValue:&result];
return result;
}
}
#pragma mark - getters and setters
- (NSMutableDictionary *)cachedTarget
{
if (!_cachedTarget) {
_cachedTarget = [[NSMutableDictionary alloc] init];
}
return _cachedTarget;
}
@end
怎么运用
运用 YJHMediator
类能够完结方针之间的解耦和相互调用。下面是运用 YJHMediator
的一般过程:
-
创立方针方针:首先,需求创立一个或多个方针方针,这些方针包括想要调用的办法。每个方针方针都应该是一个独立的类,并遵从特定的命名规矩。
-
完结方针方针的办法:在每个方针方针类中,完结想要调用的办法。保证办法的命名以 “IMP_” 最初,例如
IMP_doSomething:
。办法的参数应该是一个NSDictionary
类型的参数。 -
调用方针方针办法:在需求调用方针方针办法的当地,运用
YJHMediator
的performTarget:action:params:shouldCacheTarget:
办法来调用指定方针方针的指定办法。传入方针方针称号、办法称号和参数。依据需求,能够挑选是否缓存方针方针。 -
完结调用并处理成果:依据你的需求,能够在调用办法后处理回来的成果。
下面是一个简单的示例,演示怎么运用 YJHMediator
:
// 创立方针方针类
@interface Target_A : NSObject
- (void)IMP_doSomething:(NSDictionary *)params;
@end
@implementation Target_A
- (void)IMP_doSomething:(NSDictionary *)params {
NSString *message = params[@"message"];
NSLog(@"Target A is doing something with message: %@", message);
}
@end
// 在恰当的当地调用方针方针的办法
NSDictionary *params = @{@"message": @"Hello, XCMediator!"};
[[YJHMediator sharedInstance] performTarget:@"A" action:@"doSomething" params:params shouldCacheTarget:NO];
// 输出成果:Target A is doing something with message: Hello, XCMediator!
在上面的示例中,咱们创立了一个名为 Target_A
的方针方针类,并完结了 IMP_doSomething:
办法。然后,咱们通过 YJHMediator
的 performTarget:action:params:shouldCacheTarget:
办法调用了 Target_A
类的 doSomething
办法,并传入了一个包括音讯的参数字典。最后,Target_A
的 doSomething
办法被调用,并输出相应的日志信息。
请注意,这只是一个简单的示例,实际运用中可能涉及更杂乱的业务逻辑和多个方针方针。保证依据你的需求恰当地安排和管理方针方针和办法,并遵从命名规矩以使 YJHMediator
能够正确识别和调用它们。
示例
- 创立方针方针:首先,需求创立一个或多个方针方针,这些方针包括想要调用的办法。每个方针方针都应该是一个独立的类,并遵从特定的命名规矩。
- 完结方针方针的办法:在每个方针方针类中,完结想要调用的办法。保证办法的命名以 “IMP_” 最初,例如
IMP_doSomething:
。办法的参数应该是一个NSDictionary
类型的参数。
// Target_TTHomeMoudle.h
#import <UIKit/UIKit.h>
typedef void(^TTSearchPresentDidClickBlock)(long long, NSString *);
@interface Target_TTHomeMoudle : NSObject
- (UIViewController *)IMP_TTSearchRoomViewController:(NSDictionary *)dict;
@end
// Target_TTHomeMoudle.m
#import "Target_TTHomeMoudle.h"
#import "TTSearchRoomViewController.h"
@implementation Target_TTHomeMoudle
- (UIViewController *)IMP_TTSearchRoomViewController:(NSDictionary *)dict {
TTSearchRoomViewController *searchVC = [[TTSearchRoomViewController alloc] init];
if ([dict.allKeys containsObject:@"isPresent"]) {
searchVC.isPresent = dict[@"isPresent"];
}
if ([dict.allKeys containsObject:@"isInvite"]) {
searchVC.isInvite = dict[@"isInvite"];
}
if ([dict.allKeys containsObject:@"isHallSearch"]) {
searchVC.isHallSearch = dict[@"isHallSearch"];
}
//答应显现前史记录
if ([dict.allKeys containsObject:@"showHistoryRecord"]) {
searchVC.showHistoryRecord = [dict[@"showHistoryRecord"] boolValue];
}
if ([dict.allKeys containsObject:@"block"]) {
searchVC.searchPresentDidClickBlock = dict[@"block"];
}
if ([dict.allKeys containsObject:@"dismissBlock"]) {
searchVC.dismissAndDidClickPersonBlcok = dict[@"dismissBlock"];
}
if ([dict.allKeys containsObject:@"enterRoomBlock"]) {
searchVC.enterRoomHandler = dict[@"enterRoomBlock"];
}
return searchVC;
}
@end
- 调用方针方针办法:在需求调用方针方针办法的当地,运用
YJHMediator
的performTarget:action:params:shouldCacheTarget:
办法来调用指定方针方针的指定办法。传入方针方针称号、办法称号和参数。依据需求,能够挑选是否缓存方针方针。 - 完结调用并处理成果:依据你的需求,能够在调用办法后处理回来的成果。
例如创立一个YJHMediator的分类界说一个办法运用YJHMediator
的performTarget:action:params:shouldCacheTarget:
办法来调用指定方针方针的指定办法
// YJHMediator+TTHomeMoudle.h
#import "YJHMediator.h"
#import <UIKit/UIKit.h>
@interface YJHMediator (TTHomeMoudle)
/**
查找控制器
*/
- (UIViewController *)homeMethod_CallName_searchRoomController:(BOOL)isPresent block:(id)block;
@end
// YJHMediator+TTHomeMoudle.m
#import "YJHMediator+TTHomeMoudle.h"
@implementation YJHMediator (TTHomeMoudle)
/**
查找控制器
*/
- (UIViewController *)homeMethod_CallName_searchRoomController:(BOOL)isPresent block:(id)block {
NSDictionary *params = @{@"isPresent" : @(isPresent), @"block" : block};
return [self performTarget:@"TTHomeMoudle" action:@"TTSearchRoomViewController" params:params shouldCacheTarget:YES];
}
@end