說明:本文介紹行為型設計模式之一的中介者模式
定義
中介者模式(Mediator Pattern)又叫作調節者模式或調停者模式。用一個中介對象封裝一系列對象交互,中介者使各對象不需要顯式地互相作用,從而使其耦合松散,而且可以獨立地改變它們之間的交互,屬于行為型設計模式。
(引自《設計模式就該這樣學》P376)
中介者模式簡單來說,就是引入中間層,讓多對多關系,轉為多個一對多關系,圖示如下:
(多對多場景)
(引入中間層,轉為多個一對多)
這樣符合迪米特法則(指一個軟件實體應當盡可能少地與其他實體發生相互作用),這樣,當一個模塊修改時,就會盡量少地影響其他的模塊。
通訊交友
以兩人通訊為例,如下,
(用戶類,User)
/*** 用戶類*/
public class User {/*** 自己的名字*/private String name;/*** 定義通話對方*/private User friend;public User(String name) {this.name = name;}public String getName() {return name;}/*** 建立連接*/public void connect(User friend) {this.friend = friend;}/*** 說話* 我方說話,調用對方的listen方法*/public void talk(String msg) {friend.listen(msg);}/*** 接聽*/private void listen(String msg) {System.out.println(friend.name + " 對 " + name + " 說:" + msg);}
}
(客戶端使用,進行聊天)
public class Client {public static void main(String[] args) {User zhangsan = new User("zhangsan");User lisi = new User("lisi");zhangsan.connect(lisi);lisi.connect(zhangsan);zhangsan.talk("hello,四哥,我是三哥啊,您最近挺好的啊?");lisi.talk("哦,三哥啊,我以為誰呢,我挺好的,您呢?");}
}
開始通話
現在只有兩個人,這種設計看起來沒有問題,但如果有十個人,開一場多人會議,就要在對象內維護一個User集合,而會議人數新增或減少時,要同時改動每個對象中的User集合,這非常繁瑣還容易出問題。
聊天室
基于上面代碼的問題,我們引入一個中間層(聊天室),如下:
(用戶類,User,定義一個所屬聊天室)
/*** 用戶類*/
public class User {/*** 自己的名字*/private String name;/*** 所屬聊天室*/private Chatroom chatRoom;public User(String name) {this.name = name;}public String getName() {return name;}/*** 加入群聊*/public void login(Chatroom chatRoom) {this.chatRoom = chatRoom;chatRoom.register(this);}/*** 群內發言*/public void talk(String msg) {chatRoom.sendMsg(this, msg);}/*** 接收消息*/public void listen(User fromUser, String msg) {System.out.println("【" + this.name + "】的聊天框 【" + fromUser.getName() + "】說:" + msg);}
}
(聊天室,用來管理群成員,發消息等操作)
import java.util.ArrayList;
import java.util.List;/*** 聊天室*/
public class Chatroom {/*** 群名稱*/private String name;public Chatroom(String name) {this.name = name;}/*** 群內好友*/private List<User> users = new ArrayList<>();/*** 好友加入群聊*/public void register(User user) {this.users.add(user);System.out.println("【系統消息】" + user.getName() + "進入群聊");}/*** 群內發消息*/public void sendMsg(User fromUser, String msg) {users.stream().forEach(user -> user.listen(fromUser, msg));System.out.println("-------------------------------------------------");}
}
(客戶端測試,Client)
public class Client {public static void main(String[] args) {// 創建群,好友Chatroom chatroom = new Chatroom("各位IT界的大佬們");User zhangsan = new User("zhangsan");User lisi = new User("lisi");User wangwu = new User("王五");// 好友加入群聊zhangsan.login(chatroom);lisi.login(chatroom);// 發消息zhangsan.talk("hello,四哥,群里就你一個人啊");lisi.talk("是啊,把五哥拉進來");// 拉人進群wangwu.login(chatroom);// 發消息zhangsan.talk("哇,五哥來了");wangwu.talk("哥幾個,怎么說");}
}
怎么樣,這樣設計是不是好多了,結構一下就穩定了,無論群成員增加還是減少,現有代碼都不用改動。
使用場景
在《設計模式就該這樣學》(P378)這本書中,提到狀態模式適用于以下場景:
(1)系統中對象之間存在復雜的引用關系,產生的相互依賴關系結構混亂且難以理解。
(2)交互的公共行為,如果需要改變行為,則可以增加新的中介者類。
中介者模式,在Java三層結構開發中就有體現,Service層不會直接訪問數據庫,而是抽出DAO層,使用DAO對象訪問數據庫,就是中介者模式的一種體現,還有Spring IOC容器也是,將Bean的創建使用抽離出來統一管理。
還有,有時我們業務中,有種業務場景,沒有與之對應的實體(像User對應UserService、UserDAO),而是業務邏輯中產生的對象,如CheckService(檢查服務,根據日志表、用戶表,檢查用戶狀態是否正常),我們不直接在UserService里實現,而是抽出一個CheckService,這也是中介者模式的一種實現。
總結
本文介紹了行為型設計模式中的中介者模式,參考《設計模式就該這樣學》、《秒懂設計模式》兩書,通訊交友、聊天室場景是《秒懂設計模式》中的舉例。