簡易理解設(shè)計模式之:中介者模式——多人聊天室例子

介紹:

中介者模式屬于行為型模式。它的定義為:用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互調(diào)用,從而使其耦合松散,而且可以獨立地改變他們之間的交互。

類圖:

中介者模式UML類圖.png

Mediator(抽象中介者角色):定義一個接口用于各同事之間的通訊。
ConcreteMediator(具體中介者角色):它從具體的同事對象接受信息,向具體同事對象發(fā)出命令,負(fù)責(zé)協(xié)調(diào)同事之間的交互。
Colleague(抽象同事角色):通過中介者對象與其它同事類進(jìn)行交互,并定義所有相互影響的同事類的公共功能。
ConcreteColleagueA/B(具體同事角色):繼承于Colleague,每個具體同事類都知道本身在小范圍內(nèi)的行為,而不知道它在大范圍內(nèi)的目的。

用法:

當(dāng)對象之間的關(guān)系復(fù)雜且相互依賴時,為防止修改一個對象的行為同時涉及修改很多其它對象的行為,可使用中介者模式。

個人理解:
中介者模式的核心邏輯就是解耦對象‘多對多’的相互依賴關(guān)系。當(dāng)遇到一大堆混亂的對象呈現(xiàn)“網(wǎng)狀結(jié)構(gòu)”,利用通過中介者模式解耦對象之間的通訊。理解上就是下圖所示:

從“網(wǎng)狀結(jié)構(gòu)”到“星型結(jié)構(gòu)”.png

例子:

日常生活中,我們經(jīng)常會用社交工具(QQ、微信)進(jìn)行聊天。在這其中,群組聊天的設(shè)計正是中介者模式的例子,我們下面模擬一下:

設(shè)計思路:每個聊天用戶就相當(dāng)于同事類,聊天服務(wù)器就相當(dāng)于我們的中介者。整個流程是用戶向聊天服務(wù)器發(fā)送一條消息,服務(wù)器會將此消息發(fā)送給群組中的所有人。

設(shè)計多人聊天群組

1、創(chuàng)建抽象中介者角色

public abstract class ChatMediator {
    public abstract void register(ChatClient client);
    public abstract void notice(ChatClient client,String message);
}

定義一些接口用于同事類的通訊。在這里我們定義一個加入群聊的行為和向所有人發(fā)送通知的行為。

2、實現(xiàn)具體中介者角色

public class ChatServer extends ChatMediator {

    private List<ChatClient> clientList = new ArrayList<>();

    @Override
    public void notice(ChatClient client, String message) {
        for (ChatClient c : clientList) {
            if (!client.equals(c)) {
                c.receiveMessage(message);
            }
        }
    }

    @Override
    public void register(ChatClient client) {
        if (client != null && !clientList.contains(client)) {
            clientList.add(client);
        }
    }

}

具體中介者負(fù)責(zé)協(xié)調(diào)同事類之間的交互,notice()方法向所群組中除了自己之外的用戶發(fā)送消息。

3、創(chuàng)建抽象同事類

public abstract class ChatClient {
    protected ChatMediator mediator;

    public ChatClient(ChatMediator mediator){
        this.mediator = mediator;
    }

    public abstract void sendMessage(String message);
    public abstract void receiveMessage(String message);
}

每個用戶都有一個發(fā)送消息的方法和接收消息的方法,而消息的傳遞則通過中介者對象mediator處理。

4、實現(xiàn)具體同事類

public class Andy extends ChatClient {

    public Andy(ChatMediator mediator) {
        super(mediator);
        mediator.register(this);
    }

    @Override
    public void sendMessage(String message) {
        System.out.println();
        System.out.println("安迪發(fā)送一條消息:" + message);
        mediator.notice(this, message);
    }

    @Override
    public void receiveMessage(String message) {
        System.out.println("安迪收到一條消息:" + message);
    }
}

具體同事類忽略Ben、Cat、David等等的用戶,實現(xiàn)相似!

對于每個具體同事類(用戶)而言,它并不需要知道這個群里面到底有多少人,只知道自己是負(fù)責(zé)發(fā)送和接收消息的。

5、測試與運行結(jié)果

public class Group {

    public static void main(String[] args) {
        //聊天服務(wù)器
        ChatServer chatServer = new ChatServer();

        //三個小伙伴
        Andy andy = new Andy(chatServer);
        Ben ben = new Ben(chatServer);
        Cat cat = new Cat(chatServer);

        System.out.println("=====群聊信息=====");
        andy.sendMessage("今晚去看復(fù)仇者聯(lián)盟4吧!");
        System.out.println("-----——分割線——-----");
        ben.sendMessage("好啊好啊~我期待了很久!");
        System.out.println("-----——分割線---——--");
        cat.sendMessage("我來負(fù)責(zé)買票?。?!");
    }
}
=====群聊信息=====

安迪發(fā)送一條消息:今晚去看復(fù)仇者聯(lián)盟4吧!
Ben哥收到一條消息:今晚去看復(fù)仇者聯(lián)盟4吧!
貓貓收到一條消息:今晚去看復(fù)仇者聯(lián)盟4吧!
-----——分割線——-----
Ben哥發(fā)送一條消息:好啊好啊~我期待了很久!
安迪收到一條消息:好啊好啊~我期待了很久!
貓貓收到一條消息:好啊好啊~我期待了很久!
-----——分割線---——--
貓貓發(fā)送一條消息:我來負(fù)責(zé)買票?。?!
安迪收到一條消息:我來負(fù)責(zé)買票?。。?Ben哥收到一條消息:我來負(fù)責(zé)買票?。?!

每個用戶直接調(diào)用sendMessage()的方法就可以完成通訊了,就算是一個100人的大群每個用戶也不用改動代碼~

總結(jié):

? 中介者模式大大的好處就是降低類的關(guān)系復(fù)雜度,使對象可以更好地維護(hù)和擴(kuò)展。將多對多的“網(wǎng)狀結(jié)構(gòu)”轉(zhuǎn)化成一對多的“星型結(jié)構(gòu)”,復(fù)雜的交互邏輯交給了中介者了。

? 這個模式就是迪米特原則的具體體現(xiàn)。復(fù)習(xí)一下迪米特原則:

迪米特原則(Law Of Demeter,LOD),也稱最少知識原則。定義一個對象應(yīng)該對其他對象有最少的了解。

意思是只與朋友通訊(關(guān)聯(lián)度很高的類)。每個類都會必然用到其它類的屬性和方法,這稱為耦合。設(shè)計類的時候要把功能拆分,盡可能使用一個第三者的朋友來進(jìn)行兩者間的通訊。

? 另外,新手寫代碼很容易出現(xiàn)一個類文件有上千行代碼,N個成員變量放在一起相互調(diào)用。所以也不用急于使用中介者模式優(yōu)化代碼,需要考慮整個設(shè)計上是不是存在不合理的地方。

感謝您的閱讀~

轉(zhuǎn)載請注明出處喔:http://www.itdecent.cn/p/feac0f5fd817

推薦閱讀

基礎(chǔ)篇:
設(shè)計模式前篇之——UML類圖必會知識點
設(shè)計模式前篇之——一起過一下面向?qū)ο蟮母拍?/a>
創(chuàng)建型模式:
簡易理解設(shè)計模式之:簡單工廠模式——來試試接入支付功能
簡易理解設(shè)計模式之:工廠方法模式——數(shù)據(jù)存儲例子
簡易理解設(shè)計模式之:抽象工廠模式——更換數(shù)據(jù)庫例子
簡易理解設(shè)計模式之:建造者模式——學(xué)習(xí)使用“鏈?zhǔn)秸{(diào)用”
簡易理解設(shè)計模式之:原型模式——深、淺拷貝的概念
簡易理解設(shè)計模式之:單例模式——單例模式的幾種常用寫法
結(jié)構(gòu)型模式:
簡易理解設(shè)計模式之:適配器模式——Android列表視圖控件設(shè)計方式
簡易理解設(shè)計模式之:橋接模式——穿衣服經(jīng)典案例2
簡易理解設(shè)計模式之:組合模式——實現(xiàn)View中的樹狀結(jié)構(gòu)
簡易理解設(shè)計模式之:裝飾模式——穿衣服經(jīng)典案例
簡易理解設(shè)計模式之:外觀模式——第三方SDK的幫助類
簡易理解設(shè)計模式之:享元模式——五子棋游戲例子
簡易理解設(shè)計模式之:代理模式——iOS視圖控件設(shè)計方式
行為型模式:
簡易理解設(shè)計模式之:策略模式——優(yōu)化一下支付功能
簡易理解設(shè)計模式之:模板方法模式——Android中的BaseActivity基類
簡易理解設(shè)計模式之:觀察者模式——監(jiān)聽與回調(diào)
簡易理解設(shè)計模式之:狀態(tài)模式——優(yōu)化登錄操作
簡易理解設(shè)計模式之:備忘錄模式——Word文檔的工作原理
簡易理解設(shè)計模式之:迭代器模式——遍歷對象的好幫手
簡易理解設(shè)計模式之:命令模式——實現(xiàn)命令的參數(shù)化配置
簡易理解設(shè)計模式之:責(zé)任鏈模式——OA中請假流程示例
簡易理解設(shè)計模式之:中介者模式——多人聊天室例子
簡易理解設(shè)計模式之:解釋器模式——語言和文法
簡易理解設(shè)計模式之:訪問者模式——員工考核例子

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容