iOS 三种组件化方案

趁着这段项目空闲期,把项目中用到的组件化方案记录一下,免得遗忘。
简介
组件化是为了各个模块不直接调用,降低耦合度,都是通过中间件来实现的,草图如下

iOS 三种组件化方案_第1张图片
Snip20171128_4.png

三种方案如下

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;

具体实现就是把procotolclass做一个映射,同时在内存中保存一张映射表,使用的时候,就通过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应用架构谈 组件化方案

你可能感兴趣的:(iOS 三种组件化方案)