组件化方案|组件化方案 阅读笔记

组件 从功能业务角度上看不能在查分,适可替换,可复用的.
模块 有多个组件组成,他可以实现一个独立的功能,一个或多个业务.
例如大众点评的美食功能是一个业务,也可以叫做"美食模块".
模块化开发 中介者

//Mediator.m 中间件代码 @implementation Mediator + (UIViewController *)OpenViewController1:(NSString *)viewId { Class cls = NSClassFromString(@"UIViewController1"); return [cls performSelector:NSSelectorFromString(@"viewController1:") withObject:@{@"viewId": viewId}]; } + (UIViewController *) OpenViewController2:(NSString *) viewId type:(NSInteger)type { Class cls = NSClassFromString(@"UIViewController2"); return [cls performSelector:NSSelectorFromString(@"viewController2:") withObject:@{@"viewId": viewId, @"type": @(type)}]; } @end

//调用者 #import "Mediator.h" @implementation ViewController - (void)gotoViewController1 { UIViewController * vc = [Mediator OpenViewController1:@"id" ]; [self.navigationController pushViewController: vc animated:YES]; }- (void) gotoViewController2 { UIViewController * vc = [Mediator OpenViewController1:@"id" type:1 ]; [self.navigationController pushViewController: vc animated:YES]; } @end

这样在调用里面就不用引用 UIViewController1和 UIViewController1 的头文件了 就不会产生相互依赖 只要在调用其他组件的时候引入 Mediator.h 就可以了.接下来就是优化这套写法,有两个优化点:
1.Mediator 每一个方法里都要写 runtime 方法,格式是确定的,这是可以抽取出来的。
2.每个组件对外方法都要在 Mediator 写一遍,组件一多 Mediator 类的长度是恐怖的。
蘑菇街为了补全本地调用的功能,为组件多加了另一种方案,就是通过 protocol-class 注册表的方式。(感觉比上面的方案要复杂很多)
首先有一个新的中间件:
//ProtocolMediator.m 新中间件 @implementation ProtocolMediator @property (nonatomic, storng) NSMutableDictionary *protocolCache //注册协议协议 - (void)registerProtocol:(Protocol *)proto forClass:(Class)cls { NSMutableDictionary *protocolCache; [protocolCache setObject:cls forKey:NSStringFromProtocol(proto)]; }- (Class)classForProtocol:(Protocol *)proto { return protocolCache[NSStringFromProtocol(proto)]; } @end

然后有一个公共Protocol文件,定义了每一个组件对外提供的接口:
//ComponentProtocol.h @protocol BookDetailComponentProtocol - (UIViewController *)bookDetailController:(NSString *)bookId; - (UIImage *)coverImageWithBookId:(NSString *)bookId; @end@protocol ReviewComponentProtocol - (UIViewController *)ReviewController:(NSString *)bookId; @end

再在模块里实现这些接口,并在初始化时调用 registerProtocol 注册。
//BookDetailComponent 组件 #import "ProtocolMediator.h" #import "ComponentProtocol.h" #import "WRBookDetailViewController.h" + (void)initComponent { [[ProtocolMediator sharedInstance] registerProtocol:@protocol(BookDetailComponentProtocol) forClass:[self class]; }- (UIViewController *)bookDetailController:(NSString *)bookId { WRBookDetailViewController *detailVC = [[WRBookDetailViewController alloc] initWithBookId:param[@"bookId"]]; return detailVC; }- (UIImage *)coverImageWithBookId:(NSString *)bookId { …. }

【组件化方案|组件化方案 阅读笔记】最后调用者通过 protocol 从 ProtocolMediator 拿到提供这些方法的 Class,再进行调用:
//WRReadingViewController.m 调用者 //ReadingViewController.m #import "ProtocolMediator.h" #import "ComponentProtocol.h" + (void)gotoDetail:(NSString *)bookId { Class cls = [[ProtocolMediator sharedInstance] classForProtocol:BookDetailComponentProtocol]; id bookDetailComponent = [[cls alloc] init]; UIViewController *vc = [bookDetailComponent bookDetailController:bookId]; [[UIApplication sharedApplication].keyWindow.rootViewController.navigationController pushViewController:vc animated:YES]; }

    推荐阅读