一胆萧、概念
1、中介者模式的動機
? 現(xiàn)在QQ和微信基本是裝機必備APP俐东,就拿QQ來說跌穗,個人聊天可以一對一,假如多人聊天呢虏辫,那么就是多對多绽昏,用戶之間的關(guān)系就是一個網(wǎng)狀結(jié)構(gòu)菇爪,這個時候可以創(chuàng)建一個QQ群,這樣大家都可以進行交互。
? 在有些軟件中盈匾,某些類/對象之間的相互調(diào)用關(guān)系錯綜復(fù)雜,類似QQ用戶之間的關(guān)系泽西,此時佛纫,我們特別需要一個類似“QQ群”一樣的中間類來協(xié)調(diào)這些類/對象之間的復(fù)雜關(guān)系,以降低系統(tǒng)的耦合度稿黄。有一個設(shè)計模式正為此而誕生喊衫,它就是中介者模式。
2杆怕、中介者模式的定義
? 中介者模式(Mediator Pattern):用一個中介對象(中介者)來封裝一系列的對象交互族购,中介者使各對象不需要顯式地相互引用,從而使其耦合松散陵珍,而且可以獨立地改變它們之間的交互寝杖。中介者模式又稱為調(diào)停者模式,它是一種對象行為型模式互纯。
? 通過引入中介者來簡化對象之間的復(fù)雜交互瑟幕,中介者模式是“迪米特法則”的一個典型應(yīng)用。
3、中介者模式的4個角色
1)Mediator(抽象中介者):它定義一個接口只盹,該接口用于與各同事對象之間進行通信辣往。
2)ConcreteMediator(具體中介者):它是抽象中介者的子類,通過協(xié)調(diào)各個同事對象來實現(xiàn)協(xié)作行為殖卑,它維持了對各個同事對象的引用站削。
3)Colleague(抽象同事類):它定義各個同事類公有的方法,并聲明了一些抽象方法來供子類實現(xiàn)孵稽,同時它維持了一個對抽象中介者類的引用许起,其子類可以通過該引用來與中介者通信。
4)ConcreteColleague(具體同事類):它是抽象同事類的子類菩鲜;每一個同事對象在需要和其他同事對象通信時园细,先與中介者通信,通過中介者來間接完成與其他同事類的通信接校;在具體同事類中實現(xiàn)了在抽象同事類中聲明的抽象方法猛频。
4、中介者類承擔了兩方面的職責
1)中轉(zhuǎn)作用(結(jié)構(gòu)性):通過中介者提供的中轉(zhuǎn)作用蛛勉,各個同事對象就不再需要顯式引用其他同事伦乔,當需要和其他同事進行通信時,可通過中介者來實現(xiàn)間接調(diào)用董习。該中轉(zhuǎn)作用屬于中介者在結(jié)構(gòu)上的支持烈和。
2)協(xié)調(diào)作用(行為性):中介者可以更進一步的對同事之間的關(guān)系進行封裝,同事可以一致的和中介者進行交互皿淋,而不需要指明中介者需要具體怎么做招刹,中介者根據(jù)封裝在自身內(nèi)部的協(xié)調(diào)邏輯,對同事的請求進行進一步處理窝趣,將同事成員之間的關(guān)系行為進行分離和封裝疯暑。該協(xié)調(diào)作用屬于中介者在行為上的支持。
5哑舒、結(jié)構(gòu)圖
二妇拯、示例
? 中介者模式的核心在于中介者類的引入。
1)先創(chuàng)建一個Mediator類洗鸵,表示抽象中介者越锈;
2)然后創(chuàng)建ConcreteMediator類,繼承自Mediator類膘滨,表示具體中介者甘凭;
3)然后創(chuàng)建Colleague類,表示抽象同事類火邓;
4)最后創(chuàng)建三個類ZhangSan丹弱、LiSi和WangWu德撬,繼承自Colleague類,表示具體同事類躲胳;
具體代碼如下:
Mediator類:
@interface Mediator : NSObject
- (void)add:(Colleague *)colleague;
- (void)sendMessage:(NSString *)message colleague:(Colleague *)colleague;
@end
@interface Mediator ()
@property(nonatomic, strong) NSMutableArray<Colleague *> *colleagues;
@end
@implementation Mediator
- (instancetype)init
{
self = [super init];
if (self) {
_colleagues = [NSMutableArray array];
}
return self;
}
- (void)add:(Colleague *)colleague {
[self.colleagues addObject:colleague];
}
- (void)sendMessage:(NSString *)message colleague:(Colleague *)colleague {}
@end
ConcreteMediator類:
@interface ConcreteMediator : Mediator
@end
@implementation ConcreteMediator
- (void)sendMessage:(NSString *)message colleague:(Colleague *)colleague {
Colleague *zhangSan = self.colleagues[0];
Colleague *liSi = self.colleagues[1];
Colleague *wangWu = self.colleagues[2];
if (colleague == zhangSan) {
[liSi getMessage:message]; // 通過中介者調(diào)用同事類的方法
[wangWu getMessage:message];
} else if (colleague == liSi) {
[zhangSan getMessage:message];
}
}
@end
Colleague類:
@interface Colleague : NSObject
@property(nonatomic, strong) Mediator *mediator; //維持一個抽象中介者的引用
- (instancetype)initWithMediator:(Mediator *)mediator;
- (void)sendMessage:(NSString *)message; //定義依賴方法蜓洪,與中介者進行通信
- (void)getMessage:(NSString *)message; //聲明自身方法,處理自己的行為
@end
@implementation Colleague
- (instancetype)initWithMediator:(Mediator *)mediator {
self = [super init];
if (self) {
_mediator = mediator;
}
return self;
}
- (void)sendMessage:(NSString *)message {}
- (void)getMessage:(NSString *)message {}
@end
ZhangSan坯苹、LiSi和WangWu類:
// ZhangSan
@interface ZhangSan : Colleague
@end
@implementation ZhangSan
- (void)sendMessage:(NSString *)message {
NSLog(@"張三發(fā)送消息:%@", message);
[self.mediator sendMessage:message colleague:self];
}
- (void)getMessage:(NSString *)message {
NSLog(@"張三接收消息:%@", message);
}
@end
// LiSi
@interface LiSi : Colleague
@end
@implementation LiSi
- (void)sendMessage:(NSString *)message {
NSLog(@"李四發(fā)送消息:%@", message);
[self.mediator sendMessage:message colleague:self];
}
- (void)getMessage:(NSString *)message {
NSLog(@"李四接收消息:%@", message);
}
@end
// WangWu
@interface WangWu : Colleague
@end
@implementation WangWu
- (void)sendMessage:(NSString *)message {
NSLog(@"王五發(fā)送消息:%@", message);
[self.mediator sendMessage:message colleague:self];
}
- (void)getMessage:(NSString *)message {
NSLog(@"王五接收消息:%@", message);
}
@end
運行代碼:
- (void)viewDidLoad {
[super viewDidLoad];
// 創(chuàng)建中介者對象
ConcreteMediator *mediator = [ConcreteMediator new];
// 創(chuàng)建同事對象蝠咆,傳入同一個中介者
Colleague *zhangSan = [[ZhangSan alloc] initWithMediator:mediator];
Colleague *liSi = [[LiSi alloc] initWithMediator:mediator];
Colleague *wangWu = [[WangWu alloc] initWithMediator:mediator];
// 給中介者綁定三個對象
[mediator add:zhangSan];
[mediator add:liSi];
[mediator add:wangWu];
// 發(fā)送消息
[zhangSan sendMessage:@"我愛你們"];
NSLog(@"-----------------------");
[liSi sendMessage:@"我不喜歡張三"];
}
打印結(jié)果:
張三發(fā)送消息:我愛你們
李四接收消息:我愛你們
王五接收消息:我愛你們
-----------------------
李四發(fā)送消息:我不喜歡張三
張三接收消息:我不喜歡張三
三、總結(jié)
? 中介者模式將一個網(wǎng)狀的系統(tǒng)結(jié)構(gòu)變成一個以中介者對象為中心的星形結(jié)構(gòu)北滥,在這個星型結(jié)構(gòu)中,使用中介者對象與其他對象的一對多關(guān)系來取代原有對象之間的多對多關(guān)系闸翅。
1再芋、優(yōu)點
1、簡化了對象之間的交互:它用中介者和同事的一對多交互代替了原來同事之間的多對多交互坚冀,一對多關(guān)系更容易理解济赎、維護和擴展,將原本難以理解的網(wǎng)狀結(jié)構(gòu)轉(zhuǎn)換成相對簡單的星型結(jié)構(gòu)记某。
2司训、可將各同事對象解耦:中介者有利于各同事之間的松耦合,我們可以獨立的改變和復(fù)用每一個同事和中介者液南,增加新的中介者和新的同事類都比較方便壳猜,更好地符合“開閉原則”。
3滑凉、減少子類生成:中介者將原本分布于多個對象間的行為集中在一起统扳,改變這些行為只需生成新的中介者子類即可,這使各個同事類可被重用畅姊,無須對同事類進行擴展咒钟。
2、缺點
? 在具體中介者類中包含了大量同事之間的交互細節(jié)若未,可能會導(dǎo)致具體中介者類非常復(fù)雜朱嘴,使得系統(tǒng)難以維護。
3粗合、適用場景
1萍嬉、系統(tǒng)中對象之間存在復(fù)雜的引用關(guān)系,系統(tǒng)結(jié)構(gòu)混亂且難以理解隙疚。
2帚湘、一個對象由于引用了其他很多對象并且直接和這些對象通信,導(dǎo)致難以復(fù)用該對象甚淡。
3大诸、想通過一個中間類來封裝多個類中的行為捅厂,而又不想生成太多的子類∽嗜幔可以通過引入中介者類來實現(xiàn)焙贷,在中介者中定義對象交互的公共行為,如果需要改變行為則可以增加新的具體中介者類贿堰。
4辙芍、iOS應(yīng)用舉例
? 在進行iOS組件化的時候,就是利用中介者模式處理組件之間的交互羹与。
Demo地址:iOS-Design-Patterns