
常见组件化方式
url-block
protocol-class
target-action
组件化实施
当 App 业务之间交叉耦合,bug 率难以下降,测试每天做大量重复工作。开发人员之间修改相互影响时,你需要考虑进行组件化。
组件化是项目架构层面的技术,不是所有项目都适合组件化,组件化一般针对的是大中型的项目,并且是多人开发。
常见组件化方式
- url-block
- protocol-class
- arget-action
url-block
蘑菇街中使用的一种页面间调用的方式,通过在启动时注册组件提供的服务,把调用组件使用的 url 和组件提供的服务 block 对应起来,保存到内存中。在使用组件的服务时,通过 url 找到对应的 block,然后获取服务。
- 注册:
[MGJRouter registerURLPattern:@"mgj://detail?id=:id"
toHandler:^(NSDictionary * routerParameters) {
NSNumber *id = routerParameters[@"id"];
// create view controller with id. push view controller
}];
- 调用:
[MGJRouter openURL:@"mgj://detail?id=404"]
- 存在问题
需要在内存中维护 url-block 的表,组件多了可能会有内存问题;
url 的参数传递受到限制,只能传递常规的字符串参数,无法传递非常规参数,如 UIImage、NSData 等类型;
没有区分本地调用和远程调用的情况,尤其是远程调用会因为 url 参数受限,导致一些功能受限;
组件本身依赖了中间件,且分散注册使的耦合较多
protocol-class
通过 protocol 定义服务接口,组件通过实现该接口来提供接口定义的服务,具体实现就是把 protocol 和 class 做一个映射,同时在内存中保存一张映射表,使用的时就通过 protocol 找到对应的 class 来获取需要的服务。
- 注册:
[ModuleManager registerClass:ClassA forProtocol:ProtocolA]
- 调用:
[ModuleManager classForProtocol:ProtocolA]
这种方案确实解决了方案 1url-block中无法传递非常规参数的问题,使得组件间的调用更为方便,但是它依然没有解决组件依赖中间件、内存中维护映射表、组件的分散调用的问题。设计思想和方案 url-block 类似,都是通过给组件加了一层 wrapper,然后给使用者调用。
target-action
target-action 的方案是通过给组件包装一层 wrapper 来给外界提供服务,然后调用者通过依赖中间件来使用服务;其中,中间件是通过 runtime 来调用组件的服务,是真正意义上的解耦,也是该方案最核心的地方。具体实施过程是给组件封装一层 target 对象来对外提供服务,不会对原来组件造成入侵;然后,通过实现中间件的 category 来提供服务给调用者,这样使用者只需要依赖中间件,而组件则不需要依赖中间件。
- (UIViewController *)CTMediator_viewControllerForDetail
{
return [self performTarget:kCTMediatorTargetA
action:kCTMediatorActionNativFetchDetailViewController
params:@{ @"key" : @"value" }
shouldCacheTarget:NO];
}
组件间调用时用字典传递数据,组件内调用时用 model 传递数据,这样既减少组件间数据对 model 的耦合,又方便了组件内使用 model 传递数据的便捷性。
组件化实施
组件化可以利用 git 的源代码管理工具的便利性来实施,具体就是建立一个项目工程的私有化仓库,然后把各个组件的 podspec 上传到私有仓库,在需要用到组件时,直接从仓库里面取。
- 壳工程
main
AppDelegate
工程配置
Debug 页面
-
封装公共库和基础 UI 库
在具体的项目开发过程中,我们常会用到三方库和自己封装的 UI 库,我们可以把这些库封装成组件,然后在项目里用 pod 进行管理。其中,针对三方库,最好再封装一层,使我们的项目部直接依赖三方库,方便后续开发过程中的更换。 -
独立业务模块化
在开发过程中,对一些独立的模块,如:登录模块、账户模块等等,也可以封装成组件,因为这些组件是项目强依赖的,调用的频次比较多。另外,在拆分组件化的过程中,拆分的粒度要合适,尽量做到组件的独立性。同时,组件化是一个渐进的过程,不可能把一个完整的工程一下子全部组件化,要分步进行,通过不停的迭代,来最终实现项目的组件化。 -
服务接口最小化
在前两步都完成的情况下,我们可以根据组件被调用的需求来抽象出组件对外的最小化接口。这时,就可以选择具体应用哪种组件化方案来实施组件化了。
公共组件:
埋点组件
Common 组件(聚合工具类)
启动组件
性能监控组件
定位组件
图片处理组件
UIKit 封装和扩展组件
业务生命周期及通信组件
网络组件:
基于 AFNetworking 进行封装,提供 JSON 转 Model、缓存功能
DNS 加速组件
持久化组件:
基于 FMDB 进行封装组件
第三方业务组件:
分享组件
推送组件
基础业务组件:
User 组件,保存用户信息,登陆,登出状态