android 蘑菇街组件化,4. IOS 组件化(蘑菇街的路由+协议式)

为了研究组件化,我们主要是讨论 蘑菇街的路由+协议式 和 中间件

讨论第一种方式,并参考 蘑菇街IOS组件化 ,我们来实现一个可以运行的demo,并讨论优缺点。

路由

用MGJRouter 单例,通过 订阅或注册 和 发布或使用 来实现。肯定有点模糊,我们开始代码化。

确定唯一标识

通过mgj://detail?id=:id 注册,通过 mgj://detail?id=5 传递参数,首先我们找到两个url的相同点,下面代码中 我通过一个简单的算法+ (NSString *)keyWithUrlStr:(NSString *)urlStr, 得到一个 唯一标识 mgj_detail_id*, 这样就可以通过map 来注册和使用

registerURLPattern:toHandler: 注册

openURL: 调用组件

@interface MGJRouter : NSObject

// 可以在 一个统一的地方来注释

//mgj://detail?id=:id

+ (void)registerURLPattern:(NSString *)pattern

toHandler:(void(^)(NSDictionary *dic))block;

// 去触发组件的回调

//mgj://detail?id=5

+ (void)openURL:(NSString *)urlStr;

@end

@interface MGJRouter()

@property (nonatomic,strong) NSMutableDictionary * map;

@end

@implementation MGJRouter

- (instancetype)init {

if (self = [super init]) {

self.map = [NSMutableDictionary dictionary];

}

return self;

}

+ (MGJRouter *)shareManager {

static dispatch_once_t onceToken;

static MGJRouter * router = nil;

dispatch_once(&onceToken, ^{

if (router == nil) {

router = [[MGJRouter alloc] init];

}

});

return router;

}

// 可以在 一个统一的地方来注释

+ (void)registerURLPattern:(NSString *)pattern

toHandler:(void(^)(NSDictionary *dic))block {

NSString * key = [self keyWithUrlStr:pattern];

[self shareManager].map[key] = block;

}

// 去触发组件的回调

+ (void)openURL:(NSString *)urlStr {

NSString * key = [self keyWithUrlStr:urlStr];

NSLog(@"key = %@",key);

void(^block)(NSDictionary *dic) = [self shareManager].map[key];

if (block) {

NSMutableDictionary * param = nil;

NSURL * url = [NSURL URLWithString:urlStr];

NSString * query = url.query;

if (query.length) {

NSArray * items = [query componentsSeparatedByString:@"&"];

param = [NSMutableDictionary dictionary];

for (NSString * item in items) {

NSArray * littleItems = [item componentsSeparatedByString:@"="];

NSString * itemFirst = littleItems.firstObject;

NSString * itemSecond = littleItems.lastObject;

if (itemFirst && itemSecond) {

param[itemFirst] = itemSecond;

}

}

}

block(param);

}

}

//mgj://detail?id=:id

//协议名 mgj

// host detail

// query id=:id

// 把 mgj://detail?id=:id 和 mgj://detail?id=5 转变成相同的唯一key

+ (NSString *)keyWithUrlStr:(NSString *)urlStr {

NSURL * url = [NSURL URLWithString:urlStr];

NSString * query = url.query;

NSString * queryStr = @"";

if (query.length) {

NSArray * items = [query componentsSeparatedByString:@"&"];

for (NSString * item in items) {

NSString * itemFirst = [item componentsSeparatedByString:@"="].firstObject;

queryStr = [queryStr stringByAppendingString:itemFirst];

queryStr = [queryStr stringByAppendingString:@"*"];

}

}

return [NSString stringWithFormat:@"%@_%@_%@",url.scheme,url.host,queryStr];

}

@end

测试组件

// 注册一个组件(一般在启动的时候去注册)

[MGJRouter registerURLPattern:@"mgj://detail?id=:id&name=:name" toHandler:^(NSDictionary *dic) {

NSString * oneId = dic[@"id"];

NSString * name = dic[@"name"];

if (oneId && name) {

//创建组件,并从字典拿到值

DetailComposite * detail = [[DetailComposite alloc] init];

detail.oneId = oneId;

detail.name = name;

// 执行组件的方法

[detail showComposite];

}

}];

// 外界去调用 执行一个组件

[MGJRouter openURL:@"mgj://detail?id=5&name=leeDev"];

// 打印出: showComposite _ id = 5 ; name = leeDev

总结路由功能

其实就是使用 map 来存储 key -> 组件的功能 block ,通过 open 传递参数和key 直接调用这个block,并传递参数。

协议 (协议 - 类)

因为我们组件化,就是为了不暴露 我们的实现类,但是我们可以暴露一些接口,这样其实就是为了 降低耦合。

蘑菇街是通过 ModuleManager 来管理 协议 和 类的关联

主要是两个方法

@interface ModuleManager : NSObject

+ (void)registerClassName:(NSString *)className forProtocolName:(NSString *)protocolName;

+ (Class)classForProtocolName:(NSString *)protocolName;

@end

@interface ModuleManager()

@property (nonatomic,strong) NSMutableDictionary * map;

@end

@implementation ModuleManager

- (instancetype)init {

if (self = [super init]) {

self.map = [NSMutableDictionary dictionary];

}

return self;

}

+ (ModuleManager *)shareManager {

static dispatch_once_t onceToken;

static ModuleManager * router = nil;

dispatch_once(&onceToken, ^{

if (router == nil) {

router = [[ModuleManager alloc] init];

}

});

return router;

}

+ (void)registerClassName:(NSString *)className forProtocolName:(NSString *)protocolName {

[self shareManager].map[protocolName] = className;

}

+ (Class)classForProtocolName:(NSString *)protocolName {

NSString * className = [self shareManager].map[protocolName];

return NSClassFromString(className);

}

@end

假设需要获取购物车的个数

我们定义一个协议

@protocol MGJCart

+ (NSInteger)orderCount;

@end

在正在实现类里面去实现这个协议

#import "MGjCart.h"

@interface MGJCartImp : NSObject

@end

@implementation MGJCartImp

+ (NSInteger)orderCount {

//处理逻辑,并返回结果

return 40;

}

@end

注册和使用

//注册协议 我们只需要

[ModuleManager registerClassName:@"MGJCartImp" forProtocolName:@"MGJCart"];

//从class 获取的 ,就是我们 只是把 MGJCart 协议暴露出去

Class cla = [ModuleManager classForProtocolName:@"MGJCart"];

NSInteger orderCount = [(id )cla orderCount];

NSLog(@"orderCount = %@",@(orderCount));

// 打印出 orderCount = 40

优缺点

优点

降低耦合性,就是组件只是依赖url,而不需要依赖具体的类

缺点

传递 image 等对象类型麻烦,url 不支持

回调block 也很麻烦,是可以通过字典回调出来,但是需要文档写的比较清楚,才能回调出来

协议 - 类的 使用,也是比较繁琐,一般是该类的实例是一个 单例对象,因为调用的都是 + 方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值