前言
????在 App 中,我們常常遇到多個 UI 元素之間相互依賴,比如當列表框中的某一項被選中時,UILabel 會被更新為列表框中選定的值。又或者當用戶在文本框輸入了新的值時,需要將這個新的值加入到列表框的列表中。當更多的 UI 元素參與到這一錯綜復雜的關系之中時,情況可能變得難以控制,元素之間需要彼此了解并相互操作。又或者當從一個頁面跳轉到另一個頁面時,需要了解目標頁面所需參數等等。這個時候需要有一個集中化的角色組織各種 UI 元素在同一個語境下進行交互,稱之為中介者(Mediator)。
什么是中介者模式
????在面向對象的設計中鼓勵把行為分散到不同對象中,這種分散可能導致對象之間的互相聯系。在最糟糕的情況下,所有對象都彼此了解并相互操作。雖然把行為分散到不同對象增強了可復用性,但是增加的相互關聯又減少了獲得的益處。在這種情況下就需要中介者模式。中介者模式提供了一個中介類作為集中的場所,用一個中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。
什么時候使用中介者模式
- 對象之間的交互雖然定義明確但是非常復雜,導致一組對象彼此相互依賴,形成了網狀結構。若一個對象發生改變,我們也需要跟蹤與之相關聯的對象,同時做出相應的處理。
- 對象引用了許多其它對象并與其通訊,導致對象難以復用
- 想要定制一個分布在多個類中的邏輯或行為,又不想生成太多子類。
中介者模式的優缺點
中介者模式的優點
- 降低了類的復雜度,將一對多轉化成了一對一。
- 各個類之間的解耦。
- 符合迪米特原則。(一個類對于其他類知道的越少越好)
中介者模式的缺點
隨著系統規模的增大,中介者會越來越龐大,變得復雜難以維護。
Cocoa 中的中介者模式
????UIViewController
是一個抽象類,可以對其進行子類化以管理特定視圖。UIKit 框架還提供了UIViewController
用于管理導航欄和工具欄對象的子類:UINavigationController
和UITabBarController
. 一個 UITabController
可以管理多個 UINavigationController
,而這些UINavigationController
又可以管理一個或多個 UIViewController
,每個控制器都有其關聯的視圖對象。除了管理視圖(包括覆蓋視圖)之外,視圖控制器還指定導航欄中顯示的按鈕和標題。
中介者模式的實現
-
定義中介者和對象遵守的協議
@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
-
實現其方法
@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(@"對象1收到消息"); } - (void)send { NSLog(@"對象1發送消息"); if (self.mediator) { [self.mediator relay:self]; } } @end @interface ConcreteColleague2 : NSObject<Colleague> @end @implementation ConcreteColleague2 @synthesize mediator; - (void)receive { NSLog(@"對象2收到消息"); } - (void)send { NSLog(@"對象2發送消息"); if (self.mediator) { [self.mediator relay:self]; } } @end
-
最終調用對象方法時,會通過中介者進行管理、轉發。
ConcreteMediator *mediator = [ConcreteMediator new]; ConcreteColleague1 *colleague1 = [[ConcreteColleague1 alloc] init]; ConcreteColleague2 *colleague2 = [[ConcreteColleague2 alloc] init]; [mediator register:colleague1]; [mediator register:colleague2]; [colleague1 send]; [colleague2 send];
總結
????雖然對于處理應用程序行為分散到不同對象并且對象相互依存的情況,中介者模式非常有用,但是應當避免讓中介者類過于龐大而難以維護。