<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面向?qū)ο笤O(shè)計(jì)的設(shè)計(jì)模式:中介者模式

          共 4220字,需瀏覽 9分鐘

           ·

          2021-11-29 14:38

          ????關(guān)注后回復(fù)?“進(jìn)群”?,拉你進(jìn)程序員交流群????


          作者丨維他命君

          來(lái)源丨程序員維他命(ID:J_Knight_)


          定義

          中介者模式(Mediator Pattern):用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互,中介者使各對(duì)象之間不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。

          適用場(chǎng)景

          系統(tǒng)結(jié)構(gòu)可能會(huì)日益變得復(fù)雜,對(duì)象之間存在大量的相互關(guān)聯(lián)和調(diào)用,系統(tǒng)的整體結(jié)構(gòu)容易變?yōu)榫W(wǎng)狀結(jié)構(gòu)。在這種情況下,如果需要修改某一個(gè)對(duì)象,則可能會(huì)要跟蹤和該對(duì)象關(guān)聯(lián)的其他所有對(duì)象,并進(jìn)行處理。耦合越多,修改的地方就會(huì)越多。

          如果我們使用中介者對(duì)象,則可以將系統(tǒng)的網(wǎng)狀結(jié)構(gòu)變成以中介者為中心的星型結(jié)構(gòu)。中介者承擔(dān)了中轉(zhuǎn)作用和協(xié)調(diào)作用,簡(jiǎn)化了對(duì)象之間的交互,而且還可以給對(duì)象間的交互進(jìn)行進(jìn)一步的控制。

          現(xiàn)在我們清楚了中介者模式的適用場(chǎng)景,下面看一下中介者模式的成員和類圖。

          成員與類圖

          成員

          中介者模式一共有四個(gè)成員:

          1. 抽象中介者(Mediator):抽象中介者定義具體中介者需要實(shí)現(xiàn)的接口。

          2. 具體中介者(Concrete Mediator):具體中介者實(shí)現(xiàn)抽象中介者定義的接口,承擔(dān)多個(gè)具體同事類之間的中介者的角色。

          3. 抽象同事類(Colleague):抽象同事類定義具體同事類需要實(shí)現(xiàn)的接口。

          4. 具體同事類(Concrete Colleague):具體同事類實(shí)現(xiàn)抽象同事類定義的接口。

          模式類圖

          狀態(tài)模式類圖

          代碼示例

          場(chǎng)景概述

          模擬一個(gè)多人對(duì)話的場(chǎng)景:當(dāng)一個(gè)人發(fā)出消息后,另外的那些人可以收到該消息。

          場(chǎng)景分析

          假設(shè)一共有A,B,C三個(gè)人,那么當(dāng)A發(fā)出消息后,需要分別傳遞給B,C二人。如果三個(gè)人直接相互通信,可能偽代碼會(huì)是這樣的:

          A?sent?message?to?B
          A?sent?message?to?C

          而且隨著人數(shù)的增多,代碼行數(shù)也會(huì)變多,這顯然是不合理的。

          因此在這種場(chǎng)景下,我們需要使用中介者模式,在所有人中間來(lái)做一個(gè)消息的多路轉(zhuǎn)發(fā):當(dāng)A發(fā)出消息后,由中介者來(lái)發(fā)送給B和C:

          A?sent?message?to?Mediator?;
          Mediator?sent?message?to?B?&?C

          下面我們看一下如何用代碼來(lái)模擬該場(chǎng)景。

          代碼實(shí)現(xiàn)

          首先我們創(chuàng)建通話的用戶類User:

          //==================?User.h?==================

          @interface?User?:?NSObject

          -?(instancetype)initWithName:(NSString?*)name?mediator:(ChatMediator?*)mediator;

          -?(void)sendMessage:(NSString?*)message;

          -?(void)receivedMessage:(NSString?*)message;

          @end



          //==================?User.m?==================

          @implementation?User
          {
          ????NSString?*_name;
          ????ChatMediator?*_chatMediator;
          }

          -?(instancetype)initWithName:(NSString?*)name?mediator:(ChatMediator?*)mediator{

          ????self?=?[super?init];
          ????if?(self)?{
          ????????_name?=?name;
          ????????_chatMediator?=?mediator;
          ????}
          ????return?self;
          }

          -?(void)sendMessage:(NSString?*)message{

          ????NSLog(@"================");
          ????NSLog(@"%@?sent?message:%@",_name,message);
          ????[_chatMediator?sendMessage:message?fromUser:self];

          }

          -?(void)receivedMessage:(NSString?*)message{

          ????NSLog(@"%@?has?received?message:%@",_name,message);
          }

          @end

          用戶類在初始化的時(shí)候需要傳入中介者的實(shí)例,并持有。目的是為了在后面發(fā)送消息的時(shí)候把消息轉(zhuǎn)發(fā)給中介者。

          另外,用戶類還對(duì)外提供了發(fā)送消息和接收消息的接口。而在發(fā)送消息的方法內(nèi)部其實(shí)調(diào)用的是中介者的發(fā)送消息的方法(因?yàn)橹薪檎叱钟辛怂杏脩舻膶?shí)例,因此可以做多路轉(zhuǎn)發(fā)),具體是如何做的我們可以看下中介者類ChatMediator的實(shí)現(xiàn):

          //==================?ChatMediator.h?==================

          @interface?ChatMediator?:?NSObject

          -?(void)addUser:(User?*)user;

          -?(void)sendMessage:(NSString?*)message?fromUser:(User?*)user;

          @end



          //==================?ChatMediator.m?==================

          @implementation?ChatMediator
          {
          ????NSMutableArray?*_userList;
          }

          -?(instancetype)init{

          ????self?=?[super?init];

          ????if?(self)?{
          ????????_userList?=?[NSMutableArray?array];
          ????}
          ????return?self;
          }

          -?(void)addUser:(User?*)user{

          ????[_userList?addObject:user];
          }

          -?(void)sendMessage:(NSString?*)message?fromUser:(User?*)user{

          ????[_userList?enumerateObjectsUsingBlock:^(User?*?_Nonnull?iterUser,?NSUInteger?idx,?BOOL?*?_Nonnull?stop)?{

          ????????if?(iterUser?!=?user)?{
          ????????????[iterUser?receivedMessage:message];
          ????????}
          ????}];
          }

          @end

          中介者類提供了addUser:的方法,因此我們可以不斷將用戶添加到這個(gè)中介者里面(可以看做是注冊(cè)行為或是“加入群聊”)。在每次加入一個(gè)User實(shí)例后,都將這個(gè)實(shí)例添加到中介者持有的這個(gè)可變數(shù)組里。于是在將來(lái)中介者就可以通過(guò)遍歷數(shù)組的方式來(lái)做消息的多路轉(zhuǎn)發(fā),具體實(shí)現(xiàn)可以看sendMessage:fromUser:這個(gè)方法。

          到現(xiàn)在為止,用戶類和中介者類都創(chuàng)建好了,我們看一下消息是如何轉(zhuǎn)發(fā)的:

          ChatMediator?*cm?=?[[ChatMediator?alloc]?init];

          User?*user1?=?[[User?alloc]?initWithName:@"Jack"?mediator:cm];
          User?*user2?=?[[User?alloc]?initWithName:@"Bruce"?mediator:cm];
          User?*user3?=?[[User?alloc]?initWithName:@"Lucy"?mediator:cm];

          [cm?addUser:user1];
          [cm?addUser:user2];
          [cm?addUser:user3];

          [user1?sendMessage:@"happy"];
          [user2?sendMessage:@"new"];
          [user3?sendMessage:@"year"];

          從代碼中可以看到,我們這里創(chuàng)建了三個(gè)用戶,分別加入到了聊天中介者對(duì)象里。再后面我們分別讓每個(gè)用戶發(fā)送了一條消息。我們下面通過(guò)日至輸出來(lái)看一下每個(gè)用戶的消息接收情況:

          [13806:1284059]?================
          [13806:1284059]?Jack?sent?message:happy
          [13806:1284059]?Bruce?has?received?message:happy
          [13806:1284059]?Lucy?has?received?message:happy
          [13806:1284059]?================
          [13806:1284059]?Bruce?sent?message:new
          [13806:1284059]?Jack?has?received?message:new
          [13806:1284059]?Lucy?has?received?message:new
          [13806:1284059]?================
          [13806:1284059]?Lucy?sent?message:year
          [13806:1284059]?Jack?has?received?message:year
          [13806:1284059]?Bruce?has?received?message:year

          下面看一下上面代碼對(duì)應(yīng)的類圖。

          代碼對(duì)應(yīng)的類圖

          中介者模式代碼示例類圖

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

          • 中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散。

          缺點(diǎn)

          • 在具體中介者類中包含了同事類之間的交互細(xì)節(jié),可能會(huì)導(dǎo)致具體中介者類非常復(fù)雜,使得其難以維護(hù)。


          iOS SDK 和 JDK中的應(yīng)用

          • JDK中的Timer就是中介者類的實(shí)現(xiàn),而配合使用的TimerTask則是同事類的實(shí)現(xiàn)。



          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?面試題?資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 56
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻天天色 | 国内最新成人AV | 国产玖玖在线 | 亚洲123区| 毛片激情|