趁着这段项目空闲期,把项目中用到的组件化方案记录一下,免得遗忘。
简介
组件化是为了各个模块不直接调用,降低耦合度,都是通过中间件来实现的,草图如下
三种方案如下
1.蘑菇街URL路由方案
2.Target-Action方案
3.procotol-class方案
蘑菇街URL路由方案
URL路由方案参考的是蘑菇街MGJRouter方案
蘑菇街 App 的组件化之路
Target-Action方案
这个方案是根据casa大神的CTMediator的组件修改的,稍微修改下调用方法,和当前项目跟切合
- (id)performTargetName:(NSString *)targetName actionName:(NSString *)actionName param:(NSDictionary *)dicParam;
可以在每个模块对中间件加一个category,这样通过调用category方法,来降低耦合度,这是category的实现方法
static NSString *const kBookTarget = @"BookTarget";
static NSString *const kBookAction = @"bookVCWithParam";
@implementation SYMediator (BookVC)
- (UIViewController *)bookViewControllerWithDicParam:(NSDictionary *)dicParm
{
UIViewController *vc = [self performTargetName:kBookTarget actionName:kBookAction param:dicParm];
if ([vc isKindOfClass:[UIViewController class]]) {
return vc;
} else {
return [[UIViewController alloc] init];
}
}
当然也不可以增加category,也可以实现。
NSDictionary *dicParm = @{@"bookName" : @"降龙十八掌",@"bookid" : @"sy0001"};
//第一种方式(有category)
UIViewController *bookVC = [[SYMediator shareInstance] bookViewControllerWithDicParam:dicParm];
[self.navigationController pushViewController:bookVC animated:YES];
//第二种方式 其实不对SYMediator 增加Category也是可以实现的,就是代码比较恶心而已 下面就是例子
// UIViewController *bookVC2 = [[SYMediator shareInstance] performTargetName:@"BookTarget" actionName:@"bookVCWithParam" param:dicParm];
// [self.navigationController pushViewController:bookVC2 animated:YES];
bang
大神的总结 组件通过中间件通信,中间件通过 runtime 接口解耦,通过 target-action 简化写法,通过 category 感官上分离组件接口代码
procotol-class方案
这种方案是蘑菇街为了补全本地调用的功能,为组件多加了另一种方案,就是通过 protocol-class 注册表的方式
还是通过一个中间件来实现的
- (void)registerProtocol:(Protocol *)protocl forClass:(id)provide;
- (id)classForProtol:(Protocol *)protocol;
具体实现就是把procotol
和class
做一个映射,同时在内存中保存一张映射表,使用的时候,就通过protocol
找到对应的class来获取需要的服务
- (void)registerProtocol:(Protocol *)protocl forClass:(id)provide
{
if (!protocl || !provide) {
return;
}
NSString *protocolName = NSStringFromProtocol(protocl);
[self.protocolCache setObject:provide forKey:protocolName];
}
- (id)classForProtol:(Protocol *)protocol
{
if (!protocol) {
return nil;
}
return self.protocolCache[NSStringFromProtocol(protocol)];
}
在每个模块内定义一个公共Procotol文件,定义对外的接口
//ProtocolBookProtocol.h
@protocol ProtocolBookProtocol
- (UIViewController *)bookVCWithParam:(NSDictionary *)dicParm;
@end
最后在模块里实现这些接口
// procotol-class 方案 有点绕 这个方案跟刚才两个最大的不同就是,它不是直接通过 Mediator 调用组件方法,而是通过 Mediator 拿到组件对象,再自行去调用组件方法
NSDictionary *dicParm = @{@"bookName" : @"降龙十八掌",@"bookid" : @"sy0001"};
//1.拿到组件对象
id protocolBookManager = [[ProcotolManagerTool shareInstance] classForProtol:@protocol(ProtocolBookProtocol)];
//2.通过组件对象 再传值
UIViewController *bookVC = [protocolBookManager bookVCWithParam:dicParm];
[self.navigationController pushViewController:bookVC animated:YES];
demo
参考链接:
iOS 组件化方案探索
蘑菇街 App 的组件化之路
iOS应用架构谈 组件化方案