5. 中間件組件化

在上篇文章我們討論一下,url方式和缺點(diǎn)权均,我們現(xiàn)在來(lái)討論通過(guò),中間件來(lái)實(shí)現(xiàn)解耦髓绽。 主要是參考 CTMediator,來(lái)實(shí)現(xiàn)我們的組件化敛苇。筆者考慮到CTMediator 當(dāng)做一個(gè)單例來(lái)處理(內(nèi)部有個(gè)target緩存),我不太想這樣處理顺呕,我覺(jué)得Mediator 就是一個(gè) 工具類(lèi)枫攀,通過(guò)傳遞 組件的target 和 sel,其實(shí)就是一個(gè)加方法 就可以的株茶。

中間件代碼

這個(gè)中間件来涨,其實(shí)就是一個(gè)動(dòng)態(tài)解析的過(guò)程,把哪些組件的使用放到動(dòng)態(tài)解析中启盛,這里就不用注冊(cè)了蹦掐。

下面是筆者改造后的中間件,主要有三部分組成

  • target: 目標(biāo)組件僵闯,我們一邊抽離一個(gè)工具類(lèi)(使用 門(mén)面模式)
  • action: 調(diào)用方法
  • param: 傳遞參數(shù)卧抗,和使用回調(diào)

代碼如下

//傳遞回調(diào)值
typedef void(^ZLMediatorCallBack)(id param);
extern NSString * const ZLMediatorCallBackKey; //可以放在 param 中

@interface ZLMediator : NSObject

// 本地組件調(diào)用入口
+ (id)Mediator_PerformTargetName:(NSString *)targetName
                      actionName:(NSString *)actionName
                          params:(NSDictionary *)params;


@end



NSString * const ZLMediatorCallBackKey = @"ZLMediatorCallBackKey";
@implementation ZLMediator
// 本地組件調(diào)用入口
+ (id)Mediator_PerformTargetName:(NSString *)targetName actionName:(NSString *)actionName params:(NSDictionary *)params {
    
    Class targetClass = targetName.length > 0 ? NSClassFromString(targetName) : nil;
    NSString * msg = [NSString stringWithFormat:@"不存在Target類(lèi)名為:%@",targetName];
    NSAssert(targetClass, msg);
    
    SEL action = actionName.length > 0 ?  NSSelectorFromString(actionName) : nil;
    msg = [NSString stringWithFormat:@"Target_%@ 不存在 action為:%@",targetName,actionName];
    NSAssert(action, msg);
    
    if ([targetClass respondsToSelector:action]) {
        return [self SafePerformAction:action target:targetClass params:params];
    } else {
        msg = [NSString stringWithFormat:@"Target_%@ 不能響應(yīng) action_%@",targetName,actionName];
        NSAssert(0, msg);
    }
    return nil;
}


+ (id)SafePerformAction:(SEL)action target:(id)target params:(NSDictionary *)params {
    
    NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
    if(methodSig == nil) {
        return nil;
    }
    const char* retType = [methodSig methodReturnType];
    
    if (strcmp(retType, @encode(void)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        return nil;
    }
    
    if (strcmp(retType, @encode(NSInteger)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        NSInteger result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
    if (strcmp(retType, @encode(BOOL)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        BOOL result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
    if (strcmp(retType, @encode(CGFloat)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        CGFloat result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
    if (strcmp(retType, @encode(NSUInteger)) == 0) {
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
        [invocation setArgument:&params atIndex:2];
        [invocation setSelector:action];
        [invocation setTarget:target];
        [invocation invoke];
        NSUInteger result = 0;
        [invocation getReturnValue:&result];
        return @(result);
    }
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
}

@end

方便使用中間件

1.使用門(mén)面模式來(lái)暴露組件的使用

@interface Detail_Target : NSObject
+ (void)Target_showWithParam:(NSDictionary *)param;
@end

// 門(mén)面模式 定義方法
@implementation Detail_Target
+ (void)Target_showWithParam:(NSDictionary *)param {
    DetailComposite2 * detail = [[DetailComposite2 alloc] init];
    detail.oneId = param[@"id"];
    detail.name  = param[@"name"];
    // 執(zhí)行組件的方法
    [detail showComposite];
}
@end

然后使用就可以

[ZLMediator Mediator_PerformTargetName:@"Detail_Target"
                                actionName:@"Target_showWithParam:"
                                    params:@{@"id":@"1", @"name":@"leeDev"}];
//打印出 showComposite2 _ id = 1 ; name = leeDev

Mediator 擴(kuò)展

但是這樣傳遞參數(shù)還是比較麻煩,所用我們可以使用 Media category 來(lái)簡(jiǎn)化我們的調(diào)用鳖粟,讓使用者更加明確

@interface ZLMediator (Detail)
//直接把 target 和 sel 和param 給屏蔽了社裆,只給外界暴露 簡(jiǎn)單的接口
+ (void) detailShowWithId:(NSString *)id name:(NSString *)name;
@end

@implementation ZLMediator (Detail)

//直接把 target 和 sel 和param 給屏蔽了,只給外界暴露 簡(jiǎn)單的接口
+ (void) detailShowWithId:(NSString *)id name:(NSString *)name {
    NSDictionary * param = @{@"id":id, @"name":name};
    [ZLMediator Mediator_PerformTargetName:@"Detail_Target"
                                actionName:@"Target_showWithParam:"
                                    params:param];
}

@end

測(cè)試和使用

[ZLMediator detailShowWithId:@"10" name:@"leeDev"];
// 打印出 showComposite2 _ id = 10 ; name = leeDev

顯然相當(dāng)于上一種方法直接調(diào)用向图,這個(gè)方法要簡(jiǎn)單明確多了泳秀,直接屏蔽了 target 和 sel 和param.

優(yōu)缺點(diǎn)

相對(duì)于蘑菇街的路由和協(xié)議方式的架構(gòu)标沪,這個(gè)方式要強(qiáng)大多了

  • 可以傳遞任意值
  • 不需要注冊(cè),浪費(fèi)內(nèi)存
  • 可以通過(guò)Mediator擴(kuò)展嗜傅,來(lái)定義更加清晰的接口給外界使用金句。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市磺陡,隨后出現(xiàn)的幾起案子趴梢,更是在濱河造成了極大的恐慌,老刑警劉巖币他,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坞靶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蝴悉,警方通過(guò)查閱死者的電腦和手機(jī)彰阴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拍冠,“玉大人尿这,你說(shuō)我怎么就攤上這事∏於牛” “怎么了射众?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晃财。 經(jīng)常有香客問(wèn)我叨橱,道長(zhǎng),這世上最難降的妖魔是什么断盛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任罗洗,我火速辦了婚禮,結(jié)果婚禮上钢猛,老公的妹妹穿的比我還像新娘伙菜。我一直安慰自己,他們只是感情好命迈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布贩绕。 她就那樣靜靜地躺著,像睡著了一般躺翻。 火紅的嫁衣襯著肌膚如雪丧叽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天公你,我揣著相機(jī)與錄音踊淳,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛迂尝,可吹牛的內(nèi)容都是我干的脱茉。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼垄开,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼琴许!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起溉躲,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榜田,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后锻梳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體箭券,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年疑枯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辩块。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荆永,死狀恐怖废亭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情具钥,我是刑警寧澤豆村,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站骂删,受9級(jí)特大地震影響你画,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桃漾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拟逮。 院中可真熱鬧撬统,春花似錦、人聲如沸敦迄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)罚屋。三九已至苦囱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脾猛,已是汗流浹背撕彤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羹铅。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓蚀狰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親职员。 傳聞我的和親對(duì)象是個(gè)殘疾皇子麻蹋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容