iOS组件化开发

来源:互联网 发布:java编写飞机大战思路 编辑:程序博客网 时间:2024/06/05 18:55

一 . 为什么要组件化?
对于一些小的项目,有一个或者两三个人可以独立完成的项目,没有必要用组件化开发。组件化开发主要是为了解决项目越来越大,开发人员越来越多,项目耦合性高,不利于维护的问题。

二 . 什么是组件化?
1.组件:一般来说用于命名比较小的功能块,如:下拉刷新组件、提示框组件。而较大粒度的业务功能,我们习惯称之为”模块”。
2.组件化:也可称为模块化,用来分隔,组织和打包软件,每个特定的模块完成特定的功能,所有的模块按照特定的需求组织在一起,完成某些功能,形成一个整体。这就是组件化。
3.组件化首先思考的是模块的拆分,一般可以拆分成基础模块和业务模块,基础模块主要是提供一些基础服务,底层实现,可能很多业务模块都要依赖基础模块。例如网络请求模块。

三 . 组件化有什么优缺点?
1.优点:解除耦合性,便于团队合作开发,模块可以单独运行,测试,加快编译速度(较少主工程里的编译文件),业务分层、解耦,使代码变得可以维护,便于各业务功能拆分、抽离,实现真正的功能复用。通过url跳转,可以动态的控制页面跳转,可以统一处理页面出问题之后的错误处理,可以统一三端,iOS,Android,H5。
2.缺点:增加了很多重复代码,组件维护问题,对于版本更新迭代快,多个版本同时开发的可能还会有组件之间不同版本的依赖问题。
总之,组件化开发有优点,也有缺点,但是总的来说优点还是大于缺点的。开发中可以根据情况来确定是否需要组件化开发。
四 . 怎么实现组件化?
1.工程要分成几个模块,哪些是基础模块,哪些是业务模块,业务模块可能比较大,此时有要把大的业务模块分成几个小的业务模块。具体怎么分要考虑实际情况。
2.模块划分完成以后,各个模块之间的通信怎么实现,比较常用的中间件,通过中间件实现模块之间的通信。中间件是联系各个模块之间的通信。中间件主要做的,就是处理组件之间的页面跳转和组件之间方法的调用。
中间件的目的之一是,解除组件之间的耦合性,让各个模块独立起来。
3.从实际开发来说,组件之间最大的需求就是页面跳转,需要从组件A的pageA页面跳转到组件B的pageB页面,避免对组件B页面ViewController头文件的直接依赖。
4.组件化完成以后,就是管理组建,最常用的就是通过cocoapods管理。

五 . 组件化的原则
1.组件被定义为两种类型的组件:基础组件,业务组件。(我们还有第三方组件,属于基础组件)
2.基础组件可以被业务组件依赖,基础组件不可依赖业务组件。
3.业务组件之间不可耦合。
4.组件相互之间不能通过硬编码引用的方式进行调用。通信通过中间件实现。

六 . 组件化的过程中需要注意的问题?
1.当组件比较多的时候,它们的依赖关系、版本等的管理问题也就多了,组件管理起来可比较麻烦,可能需要制定一个组件管理机制,所以就需要集成管理。
七 . 常用的组件化方式有哪些?
1.MGJRouter
蘑菇街所采用的是 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”]

通过调用openURL来进行跳转。
蘑菇街的URL有专门的后台管理。这样 就解决了被调用者文件的引入问题,从而达到解耦。
但是他们 有 传参的问题。
从url上可以看出来,他们只能传基本参数,像对象之类的参数就无能为力。
2.CTMediator
CTMediator 是基于Target-Action模式。

-(void)addTarget:(id)target action:(SEL) forControlEvents:(UIControlEvents)controlEvents

CTMediator的做法是, 一个target对应一个mediator的category, 每个category里的方法对应了这个target下所有可能的调用场景。
下面是以news为target,所创建的category

#import "CTMediator+NewsActions.h"NSString * const kCTMediatorTarget_News = @"News";NSString * const kCTMediatorActionNativTo_NewsViewController = @"NativeToNewsViewController";@implementation CTMediator (NewsActions)- (UIViewController *)yt_mediator_newsViewControllerWithParams:(NSDictionary *)dict {    UIViewController *viewController = [self performTarget:kCTMediatorTarget_News                                                    action:kCTMediatorActionNativTo_NewsViewController                                                    params:dict];    if ([viewController isKindOfClass:[UIViewController class]]) {        return viewController;    } else {        NSLog(@"%@", NSStringFromSelector(_cmd));        return [[UIViewController alloc] init];    }}@end

通过mediator调用上面的category方法进行跳转到news页面

- (void)bButtonClick:(UIButton *)sender {        UIViewController *viewController = [[CTMediator sharedInstance] yt_mediator_newsViewControllerWithParams:@{@"newsID":@"123456"}];    [self.navigationController pushViewController:viewController animated:YES];}

相比 MGJRouter ,CTMediator使用category就可以很好的解决传参的问题。
CTMediator是组件内会提供对外开放的需要被组件外需要的类名和属性。

#import "Target_News.h"#import "NewsViewController.h"@implementation Target_News- (UIViewController *)Action_NativeToNewsViewController:(NSDictionary *)params {    NewsViewController *newsVC = [[NewsViewController alloc] init];    if ([params valueForKey:@"newsID"]) {        newsVC.newsID = params[@"newsID"];    }    return newsVC;}@end

3.LDBusMediator
LDBusMediator是利用URL->ViewController的形式。本地维护一个url与viewController的map,通过快速遍历利用url生成viewController。

[LDBusMediator routeURL:[NSURL URLWithString:@"productScheme://ADetail"] withParameters:@{@"image":@""}

从url上可以看出,LDBusMediator方案是根据scheme和host用来匹配对应的viewcontroller,然后进行跳转。
LDBusMediator传参上可以在url上后接上参数,也可以通过字典的形式传参。

八 . 从组件间调用方法的角度, 就是我们所说的中间件的服务。

1.MGJRouter
蘑菇街组件间的调用通过protocol来实现

[ModuleManager registerClass:ClassA forProtocol:ProtocolA][ModuleManager classForProtocol:ProtocolA]

蘑菇街通过ModuleManager这个类加了一个映射关系protocol->class
通过协议名拿到class,不过调用方不需要知道class的具体类名,因为协议的方法都在组件内实现,所以直接拿来用就行了。

2.CTMediator
CTMediator 组件间的调用就是通过上面讲到的category 包含了target下所有场景下调用场景。
categary中开放的 方法供调用者调用。

[[CTMediator sharedInstance] CTMediator_showAlertWithMessage:@"casa" cancelAction:nil confirmAction:^(NSDictionary *info) {            // 做你想做的事            NSLog(@"%@", info);        }];

3.LDBusMediator
LDBusMediator也是利用protocol来实现服务的调用。
LDBusMediator方案中,每个业务组件的实现自定义一个挂接点Connector_A,挂接点遵循中间件规定的connector协议;在挂接点需要连接上可导航的url,协议的服务承载实例。通过挂接点+协议的方式,组件的实现部分不用对外披露任何头文件,从而达到解耦的目的。

通过connector向BusMediator挂接可处理的Protocol,根据Protocol获取当前组件中可处理protocol的服务实例。

具体服务协议的实现可放到其他类实现文件中,只需要在当前connetor中引用,返回一个服务实例即可

[[LDBusMediator serviceForProtocol:@protocol(ModuleAXXXServicePrt)] moduleA_showAlertWithMessage:@"casa" cancelAction:nil confirmAction:^(NSDictionary *info) {            NSLog(@"%@", info);        }];