前言
????在 App 中坐桩,我們常常遇到多個(gè) UI 元素之間相互依賴尺棋,比如當(dāng)列表框中的某一項(xiàng)被選中時(shí),UILabel 會(huì)被更新為列表框中選定的值绵跷。又或者當(dāng)用戶在文本框輸入了新的值時(shí)陡鹃,需要將這個(gè)新的值加入到列表框的列表中。當(dāng)更多的 UI 元素參與到這一錯(cuò)綜復(fù)雜的關(guān)系之中時(shí)抖坪,情況可能變得難以控制萍鲸,元素之間需要彼此了解并相互操作。又或者當(dāng)從一個(gè)頁面跳轉(zhuǎn)到另一個(gè)頁面時(shí)擦俐,需要了解目標(biāo)頁面所需參數(shù)等等脊阴。這個(gè)時(shí)候需要有一個(gè)集中化的角色組織各種 UI 元素在同一個(gè)語境下進(jìn)行交互,稱之為中介者(Mediator)蚯瞧。
什么是中介者模式
????在面向?qū)ο蟮脑O(shè)計(jì)中鼓勵(lì)把行為分散到不同對(duì)象中嘿期,這種分散可能導(dǎo)致對(duì)象之間的互相聯(lián)系。在最糟糕的情況下埋合,所有對(duì)象都彼此了解并相互操作备徐。雖然把行為分散到不同對(duì)象增強(qiáng)了可復(fù)用性,但是增加的相互關(guān)聯(lián)又減少了獲得的益處甚颂。在這種情況下就需要中介者模式蜜猾。中介者模式提供了一個(gè)中介類作為集中的場(chǎng)所,用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互振诬,中介者使各對(duì)象不需要顯式地相互引用蹭睡,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互赶么。
什么時(shí)候使用中介者模式
- 對(duì)象之間的交互雖然定義明確但是非常復(fù)雜肩豁,導(dǎo)致一組對(duì)象彼此相互依賴,形成了網(wǎng)狀結(jié)構(gòu)。若一個(gè)對(duì)象發(fā)生改變清钥,我們也需要跟蹤與之相關(guān)聯(lián)的對(duì)象琼锋,同時(shí)做出相應(yīng)的處理。
- 對(duì)象引用了許多其它對(duì)象并與其通訊祟昭,導(dǎo)致對(duì)象難以復(fù)用
- 想要定制一個(gè)分布在多個(gè)類中的邏輯或行為缕坎,又不想生成太多子類。
中介者模式的優(yōu)缺點(diǎn)
中介者模式的優(yōu)點(diǎn)
- 降低了類的復(fù)雜度从橘,將一對(duì)多轉(zhuǎn)化成了一對(duì)一念赶。
- 各個(gè)類之間的解耦。
- 符合迪米特原則恰力。(一個(gè)類對(duì)于其他類知道的越少越好)
中介者模式的缺點(diǎn)
隨著系統(tǒng)規(guī)模的增大叉谜,中介者會(huì)越來越龐大,變得復(fù)雜難以維護(hù)踩萎。
Cocoa 中的中介者模式
????UIViewController
是一個(gè)抽象類停局,可以對(duì)其進(jìn)行子類化以管理特定視圖。UIKit 框架還提供了UIViewController
用于管理導(dǎo)航欄和工具欄對(duì)象的子類:UINavigationController
和UITabBarController
. 一個(gè) UITabController
可以管理多個(gè) UINavigationController
香府,而這些UINavigationController
又可以管理一個(gè)或多個(gè) UIViewController
董栽,每個(gè)控制器都有其關(guān)聯(lián)的視圖對(duì)象。除了管理視圖(包括覆蓋視圖)之外企孩,視圖控制器還指定導(dǎo)航欄中顯示的按鈕和標(biāo)題锭碳。
中介者模式的實(shí)現(xiàn)
-
定義中介者和對(duì)象遵守的協(xié)議
@protocol Mediator; @protocol Colleague <NSObject> @property (nonatomic, strong) id <Mediator> mediator; - (void)receive; - (void)send; @end @protocol Mediator <NSObject> - (void)register:(id<Colleague>)colleague; - (void)relay:(id<Colleague>)cl; @end
-
實(shí)現(xiàn)其方法
@interface ConcreteMediator : NSObject<Mediator> @end @interface ConcreteMediator () @property (nonatomic, strong) NSMutableArray <id<Colleague>> *colleagues; @end @implementation ConcreteMediator - (NSMutableArray<id<Colleague>> *)colleagues{ if (!_colleagues) { _colleagues = [NSMutableArray array]; } return _colleagues; } - (void)register:(id<Colleague>)colleague{ if ([colleague conformsToProtocol:@protocol(Colleague) ]){ if(![self.colleagues containsObject:colleague]){ [self.colleagues addObject:colleague]; [colleague setMediator:self]; } } } - (void)relay:(id<Colleague>)cl{ for (id <Colleague> colleague in self.colleagues) { if (![colleague isEqual:cl]) { [colleague receive]; } } } @end @interface ConcreteColleague1 : NSObject<Colleague> @end @implementation ConcreteColleague1 @synthesize mediator; - (void)receive { NSLog(@"對(duì)象1收到消息"); } - (void)send { NSLog(@"對(duì)象1發(fā)送消息"); if (self.mediator) { [self.mediator relay:self]; } } @end @interface ConcreteColleague2 : NSObject<Colleague> @end @implementation ConcreteColleague2 @synthesize mediator; - (void)receive { NSLog(@"對(duì)象2收到消息"); } - (void)send { NSLog(@"對(duì)象2發(fā)送消息"); if (self.mediator) { [self.mediator relay:self]; } } @end
-
最終調(diào)用對(duì)象方法時(shí),會(huì)通過中介者進(jìn)行管理勿璃、轉(zhuǎn)發(fā)擒抛。
ConcreteMediator *mediator = [ConcreteMediator new]; ConcreteColleague1 *colleague1 = [[ConcreteColleague1 alloc] init]; ConcreteColleague2 *colleague2 = [[ConcreteColleague2 alloc] init]; [mediator register:colleague1]; [mediator register:colleague2]; [colleague1 send]; [colleague2 send];
總結(jié)
????雖然對(duì)于處理應(yīng)用程序行為分散到不同對(duì)象并且對(duì)象相互依存的情況,中介者模式非常有用补疑,但是應(yīng)當(dāng)避免讓中介者類過于龐大而難以維護(hù)歧沪。