因?yàn)?a target="_blank" rel="nofollow">https://blog.csdn.net/urdfmqcul2/article/details/78788962
,博客搬家至https://juejin.im/user/59fd6315f265da4321536990
首先來看看wiki上對(duì)中介者模式的解釋:
In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program's running behavior.
在軟件工程中,中介模式定義了一個(gè)對(duì)象,該對(duì)象封裝了一組對(duì)象是如何交互的。這種模式被認(rèn)為是一個(gè)行為模式,因?yàn)樗梢愿淖兂绦虻倪\(yùn)行行為。
在一個(gè)項(xiàng)目里,我們開發(fā)的程序是由大量的類來組成的,隨著程序功能的不斷增加,類和類之間的依賴關(guān)系也跟著趨于復(fù)雜,而中介者模式便能解決這個(gè)問題。
這種復(fù)雜的依賴關(guān)系,在iOS開發(fā)當(dāng)中常用的MVC模式中定義的ViewController(VC)就是典型的代表。一般情況下一個(gè)頁面便對(duì)應(yīng)代碼中的一個(gè)VC,而一個(gè)中等規(guī)模的軟件至少會(huì)有幾十個(gè)的頁面,對(duì)應(yīng)的就是幾十個(gè)VC。(當(dāng)然你也可以說復(fù)用VC,但是在正常情況下,VC的復(fù)用場(chǎng)景會(huì)有這么多么?這里我們不考慮復(fù)用VC的情況。)而要管理這些VC之間的關(guān)系是一件非常繁瑣的事情,我們要處理各個(gè)VC之間的關(guān)系,每當(dāng)一個(gè)VC要跳轉(zhuǎn)到另外個(gè)VC,我們需要包含新的VC的頭文件,于是有的起銜接作用的頁面中包含了大量的其他VC的頭文件。同時(shí)每當(dāng)產(chǎn)品經(jīng)理要求修改一些頁面的邏輯關(guān)系,我們又需要對(duì)這些頭文件和對(duì)應(yīng)的代碼進(jìn)行修改,想想我就頭大。類似下圖:

而使用中介者模式可以非常好地去解決這個(gè)問題。實(shí)現(xiàn)一個(gè)管理VC關(guān)系的功能類,這個(gè)類的作用是給每個(gè)VC綁定一個(gè)URL,當(dāng)需要打開某一個(gè)新的VC時(shí),通過功能類的openURL接口傳入新VC的URL即可。發(fā)起openURL的一方不需要去依賴新的VC,只需要和功能類建立聯(lián)系,類似下圖:

Mediator類的作用就相當(dāng)于一個(gè)路由器(Router),將客戶發(fā)起的URL請(qǐng)求轉(zhuǎn)移到對(duì)應(yīng)的類。我們還可以利用iOS應(yīng)用本身的特點(diǎn),以及Objective-C語言的特性,給這個(gè)Router增加一些功能:
在一些特殊情況下,打開不同的頁面(VC)之后,還需要傳遞一些命令到這個(gè)VC,讓其做一些特殊的操作,于是可以通過配置URL的參數(shù),再通過參數(shù)名和參數(shù)值傳遞給新VC:
[MRRouter openURL:@"scheme://test?aa=11&bb=22"];
更方便的,可以直接用字典來傳遞參數(shù):
[MRRouter openURL:@"scheme://test3" parameters:@{@"ccc":@"333",@"ddd":@"444"}];
于是還需要?jiǎng)?chuàng)建一個(gè)映射表,來建立URL和VC之間的映射關(guān)系,每增加一個(gè)VC,就在這個(gè)表里頭增加一個(gè)對(duì)應(yīng)關(guān)系。這里可以利用Objective-C的Runtime來動(dòng)態(tài)地根據(jù)類名去映射,簡(jiǎn)化我們的日常編碼操作,具體的實(shí)現(xiàn)就不在這里詳細(xì)描述了,有興趣可以去這里看具體的實(shí)現(xiàn)。
還可以定義一個(gè)默認(rèn)的openURL操作:
[MRRouter sharedInstance].defaultExecutingBlock = ^(id object, NSDictionary *parameters) {
[self.navigationController pushViewController:object animated:YES];
};
這樣在一般情況下打開一個(gè)新的頁面,不需要引入任何頭文件,也不需要建立映射關(guān)系,只需要調(diào)用Router的openURL接口。
通過以中介者模式為基礎(chǔ)的Router管理頁面的額外好處,就是可以簡(jiǎn)化服務(wù)端push需要打開新頁面的操作,當(dāng)有一個(gè)新的活動(dòng),要打開一個(gè)對(duì)應(yīng)的頁面,只需要把這個(gè)頁面的URL通過push發(fā)送給客戶端,客戶端直接傳遞給Router即可,省略了大量的if/else的邏輯判斷。
總結(jié):
中介者模式的使用不光用在VC的管理,當(dāng)功能中出現(xiàn)了類似“多對(duì)多”的復(fù)雜的對(duì)象群時(shí),就可以用到它來管理這些對(duì)象。當(dāng)然,再次之前,你需要考慮的不應(yīng)該是開始使用中介者模式,而是考慮這個(gè)功能的設(shè)計(jì)是否合理。
使用中介者模式雖然降低了各個(gè)對(duì)象之間的耦合,減少了對(duì)象之間邏輯的復(fù)雜度,但是這個(gè)復(fù)雜度在一定程度上轉(zhuǎn)移到了Mediator類中,因此Mediator類的功能維護(hù)需要謹(jǐn)慎處理。
以上舉例中的所有代碼可以在這里下載,歡迎各種star/request/issue。