市面上比较常见的三种组件化方案.
- MGJRouter
- BeeHive
- CTMediator
MGJRouter
url-block
的方式, 根据url
找到对应的代码块
去执行.
注册和调用的简单理解
//注册url
+ (void)registerURLPattern:(NSString *)URLPattern toHandler:(MGJRouterHandler)handler;
MGJRouter的单例有一个NSMutableDictionary类型的routes的属性
例:
[MGJRouter registerURLPattern:@"mgj://foo/bar" toHandler:^(NSDictionary *routerParameters) {
[self appendLog:@"匹配到了 url,以下是相关信息"];
[self appendLog:[NSString stringWithFormat:@"routerParameters:%@", routerParameters]];
}];
这样调用了之后,等于是在MGJRouter
的单例的routes
中添加了如下键值对:
routes = {
mgj = {
foo = {
bar = {
"_" = "<__NSMallocBlock__: 0x600000d8c6f0>";
};
};
};
}
当我们调用open:url
的时候.
+ (void)openURL:(NSString *)URL;
等于是把routes
中的_
对应的block代码块
赋值给了MGJRouterHandler
的实例去执行对应的block.
优
- 将路由和代码块绑定, 自身模块的调用相对清晰.
- 参数的传递根据路由模式解析, 可以进行很好的扩展.
劣
- 硬编码问题, 每个组件的参数调用都需要查找. 蘑菇街为了统一管理自己有一套web页面, 控制url和所有的参数.
- 所有的
url
和block
注册在内存中, 组件多了之后会有内存问题. - 无法区分本地和远程的调用, 参数的限制可能导致远程功能受限
- 组件要依赖中间件, 并且分散注册耦合较多.
BeeHive
Protocol-Class
的方式, 根据Protocol
找到对应的Class
进行调用.
Class
实现Protocol
定义的外部接口Protocol
暴露出去, 供外部使用. 核心点BHModuleProtocol
: Module负责管理模块的注册和释放BHServiceProtocol
: 负责组件的开放接口
核心就是单例BHServiceManager
负责可变字典allServicesDict
属性, 存储了
NSString(协议名): NSString(类名)
取出的时候, 根据协议获取到类, 然后runtime
API创建类, 类可以调用协议内的函数和属性.
优
- 接口灵活, 可以设计灵活的回调和函数.
- 没有硬编码
- 模块间解耦
劣
- 所有的接口协议文件需要放在一起, 其他模块依赖该模块, 但是不会有实现代码.
- 使用起来麻烦, 每个调用都需要一个服务和一个协议.
CTMediator
CTMediator
target-action
的方式
- 利用
NSInvocation
类, 使用字符串targetName
和字符串actionName
转成对应的id
和SEL
类型, 利用NSInvocation
类进行方法的调用.(要注意方法的types
) 个人认为, CT使用起来还是较为容易出问题, 硬编码太多后期改动会十分麻烦.
优
- API简单, 易学.
- 侵入小
- 可以解决不同类之间的调用问题
劣
- 硬编码多,
- 运行时才可以知道, 编译器无法检 查.
组件化原则
- 抽象化原则
- 稳定性原则
- 从上到下依赖, 组间不依赖.
抽象化原则
- 最简单的评判标准就是, 上层调用的APi长久不需要改动.
- 抽象总结的能力
- 就像苹果官方一样, 每年都要求, 一定要用API, 不要轻易访问内部的数据结构.
稳定性原则
- 减少依赖, 只要自身稳定, 那么就是稳定
- 稳定的模块不可以依赖不稳定的模块
从上到下依赖, 组间不依赖, 业务间不依赖.
- 模块设计上层可以依赖下层, 下层不可以依赖上层.
- 平级模块间, 不进行依赖.
- 最好除了最底层的不可缺的依赖, 从上到下的依赖也要尽可能的避免
- 业务之间不依赖
总结
组件化的方案, 要根据具体的公司规模, 人数可能是发展去制定. 比如你公司只有两个人, 开发很忙, 加入分业务组件, 每一个都做注册, 绑定, 其实是忙不过来的.
- 人数较多维护的项目, 拆分的粒度一定要细, 可能阿里的这种方案更为合适, 解耦性好, 使用稍微麻烦.
- 人数较少维护的项目, 可以拆分的粒度很大, 甚至只是分文件夹.
- 比如一个
Model
, 在多个业务使用, 3个人的时候可以将其下沉到下部, 上部调用即可. 但是300个人的时候, 其实只能每次接收json
从新进行处理更为合适.
没有最好的方案, 只有根据当前的人手, 业务, 项目综合考虑进行方案的选型.
多看一些方案, 其实可以从众取出一些自己觉得好的设计进行融合也是不错.
个人比较建议, 路由的模式以BeeHive
为核心, 融合MGJRouter
, 然后用懒加载的方式进行模块的初始化. 并且提供非懒加载调用的模式. 系统内存泄漏时候, 可以使用weak链表进行内存的清理等等.多看看总会有很多新奇的想法.