* 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關係, * 將對象之間的通信封裝到一個中介者對象中,從而使得各個對象之間的關係更加鬆散。 * 在中介者模式中,對象之間不再直接相互交互,而是通過中介者來中轉消息。 ...
簡介
中介者模式(Mediator Pattern)是一種行為型模式。它限制對象之間的直接交互,它用一個中介對象來封裝一系列的動作,以讓對象之間進行交流。中介者使各個對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
當一些對象和其他對象緊密耦合以致難以對其進行修改時,或當組件因過於依賴其他組件而無法在不同應用中復用時,可使用中介者模式。
作用
- 用來降低多個對象和類之間的通信複雜性。
- 對象之間不再顯式地相互引用,但可以獨立地改變它們之間的交互,從而保持松耦合。
實現步驟
- 定義一個工具介面,供不同工具類來實現。建立多個具體工具類實現基礎工具介面。
- 定義一個基礎抽象類,裡面聚合了工具介面,相當於橋接。
- 再重新定義一個新抽象類,繼承自基礎抽象類,並補充一些方法。
- 建立具體對象類繼承新抽象類,調用橋接介面里的方法來實現功能。
UML
Java代碼
中介者抽象介面
// RoomMediator.java 定義中介者介面或抽象類 public interface RoomMediator { public void register(AbstractUser user); public void sendTo(AbstractUser from, AbstractUser to, String message); public void send(AbstractUser from, String message); }
通用中介者
// GeneralRoom.java 中介者的具體實現類 public class GeneralRoom implements RoomMediator { public List<AbstractUser> users = new ArrayList<AbstractUser>(); @Override public void register(AbstractUser user) { // 用戶註冊登記,追加用戶列表 user.setRoomMediator(this); users.add(user); } // 作為中介者通知給某個用戶 @Override public void sendTo(AbstractUser from, AbstractUser to, String message) { System.out.println( "GeneralRoom:sendTo() [from: " + from.getName() + " message: " + message + " to: " + to.getName() + " ]"); // 根據用戶名稱定向發送 to.recieve(from, message); } // 作為中介者通知給全體用戶 @Override public void send(AbstractUser from, String message) { System.out.println("GeneralRoom:send() [from: " + from.getName() + " message: " + message + "]"); for (AbstractUser user : users) { user.recieve(from, message); } } }
抽象用戶類
// AbstractUser.java 定義抽象用戶類,聚合中介者 public abstract class AbstractUser { private String name; public RoomMediator roomMediator; public AbstractUser(String name) { this.name = name; } public void setRoomMediator(RoomMediator roomMediator) { this.roomMediator = roomMediator; } public abstract void send(String message); public abstract void sendTo(AbstractUser to, String message); public abstract void recieve(AbstractUser from, String message); public String getName() { return this.name; } }
具體用戶對象
// CommonUser.java 普通用戶繼承了抽象用戶,實現了具體功能 public class CommonUser extends AbstractUser { public CommonUser(String name) { super(name); } @Override public void send(String message) { System.out.println("CommonUser:send() [user: " + this.getName() + " message:" + message + "]"); // 通過中介者來中轉消息 this.roomMediator.send(this, message); } @Override public void sendTo(AbstractUser to, String message) { System.out.println("CommonUser:sendTo() [user: " + this.getName() + " message:" + message + " to: " + to.getName() + "]"); // 通過中介者來中轉消息 this.roomMediator.sendTo(this, to, message); } @Override public void recieve(AbstractUser from, String message) { System.out.println("CommonUser:recieve() [user: " + this.getName() + " message: " + message + " from:" + from.getName() + "]"); } }
// MemberUser.java 會員用戶繼承了抽象用戶,實現了具體功能 public class MemberUser extends AbstractUser { public MemberUser(String name) { super(name); } @Override public void send(String message) { System.out.println("MemberUser:send() [user: " + this.getName() + " message:" + message + "]"); // 通過中介者來中轉消息 this.roomMediator.send(this, message); } @Override public void sendTo(AbstractUser to, String message) { System.out .println("MemberUser:sendTo() [user: " + this.getName() + " message:" + message + " to: " + to.getName() + "]"); // 通過中介者來中轉消息 this.roomMediator.sendTo(this, to, message); } @Override public void recieve(AbstractUser from, String message) { System.out.println("MemberUser:recieve() [user: " + this.getName() + " message: " + message + " from user:" + from.getName() + "]"); } }
測試調用
public class Test { public static void start() { /** * 中介者模式用一個中介對象來封裝一系列動作,讓對象之間利用中介者來交流。 * 這裡聊天室就是一個中介者,用戶和用戶之間的消息傳遞,全部依靠聊天室來完成。 * 先給聊天室註冊用戶,也給用戶綁定上中介者,雙方彼此持有關係。 * 中介者的成員之間的消息傳遞通過中介者來代理傳達。 */ // 聲明一個聊天室 GeneralRoom generalRoom = new GeneralRoom(); // 給聊天室添加點不同的人 AbstractUser user1 = new CommonUser("user1"); generalRoom.register(user1); CommonUser user2 = new CommonUser("user2"); generalRoom.register(user2); MemberUser user3 = new MemberUser("user3"); generalRoom.register(user3); // user1 發送給全體 user1.send("hi, I'm " + user1.getName() + "."); // user2 發送給 user3 user2.sendTo(user3, "haha."); } public static void main(String[] args) { System.out.println("test start:"); start(); } }
Go代碼
中介者抽象介面
// RoomMediator.go 定義中介者介面或抽象類 type RoomMediator interface { Register(user AbstractUser) SendTo(from AbstractUser, to AbstractUser, message string) Send(from AbstractUser, message string) }
通用中介者
// GeneralRoom.go 中介者的具體實現類 type GeneralRoom struct { users []AbstractUser } func (g *GeneralRoom) Register(user AbstractUser) { // 用戶註冊登記,追加用戶列表 user.SetRoomMediator(g) g.users = append(g.users, user) } // 作為中介者通知給某個用戶 func (g *GeneralRoom) SendTo(from AbstractUser, to AbstractUser, message string) { fmt.Println("GeneralRoom::SendTo() [from: " + from.GetName() + " message: " + message + " to: " + to.GetName() + "]") // 定向發送給某個用戶,名稱唯一 to.Recieve(from, message) } // 作為中介者通知給全體用戶 func (g *GeneralRoom) Send(from AbstractUser, message string) { fmt.Println("GeneralRoom::Send() [from: " + from.GetName() + " message: " + message + "] ") for _, user := range g.users { user.Recieve(from, message) } }
抽象用戶類
// AbstractUser.go 定義抽象用戶類,聚合中介者 type AbstractUser interface { SetRoomMediator(roomMediator RoomMediator) Send(message string) SendTo(to AbstractUser, message string) Recieve(from AbstractUser, message string) GetName() string }
具體用戶對象
// CommonUser.go 普通用戶繼承了抽象用戶,實現了具體功能 type CommonUser struct { Name string roomMediator RoomMediator } func (c *CommonUser) SetRoomMediator(roomMediator RoomMediator) { c.roomMediator = roomMediator } func (c *CommonUser) Send(message string) { fmt.Println("CommonUser:Send() [user: " + c.GetName() + " message: " + message + "]") // 通過中介者來中轉消息 c.roomMediator.Send(c, message) } func (c *CommonUser) SendTo(to AbstractUser, message string) { fmt.Println("CommonUser:SendTo() [user: " + c.GetName() + " message: " + message + "]") // 通過中介者來中轉消息 c.roomMediator.SendTo(c, to, message) } func (c *CommonUser) Recieve(from AbstractUser, message string) { fmt.Println("CommonUser:Recieve() [user: " + c.GetName() + " message: " + message + " from: " + from.GetName() + "]") } func (c *CommonUser) SetName(name string) { c.Name = name } func (c *CommonUser) GetName() string { return c.Name }
// MemberUser.go 會員用戶繼承了抽象用戶,實現了具體功能 type MemberUser struct { // Name首字母大寫以便跨模塊訪問 Name string roomMediator RoomMediator } func (c *MemberUser) SetRoomMediator(roomMediator RoomMediator) { c.roomMediator = roomMediator } func (c *MemberUser) Send(message string) { fmt.Println("MemberUser:Send() [user: " + c.GetName() + " message: " + message + "]") // 通過中介者來中轉消息 c.roomMediator.Send(c, message) } func (c *MemberUser) SendTo(to AbstractUser, message string) { fmt.Println("MemberUser:SendTo() [user: " + c.GetName() + " message: " + message + "]") // 通過中介者來中轉消息 c.roomMediator.SendTo(c, to, message) } func (c *MemberUser) Recieve(from AbstractUser, message string) { fmt.Println("MemberUser:Recieve() [user: " + c.GetName() + " message: " + message + " from: " + from.GetName() + "]") } func (c *MemberUser) SetName(name string) { c.Name = name } func (c *MemberUser) GetName() string { return c.Name }
測試調用
func main() { fmt.Println("test start:") /** * 中介者模式用一個中介對象來封裝一系列動作,讓對象之間利用中介者來交流。 * 這裡聊天室就是一個中介者,用戶和用戶之間的消息傳遞,全部依靠聊天室來完成。 * 先給聊天室註冊用戶,也給用戶綁定上中介者,雙方彼此持有關係。 * 中介者的成員之間的消息傳遞通過中介者來代理傳達。 */ // 聲明一個聊天室 var generalRoom = new(src.GeneralRoom) // 給聊天室添加點不同的人 var user1 = &src.CommonUser{ Name: "user1", } generalRoom.Register(user1) var user2 = &src.CommonUser{ Name: "user2", } generalRoom.Register(user2) var user3 = &src.MemberUser{ Name: "user3", } generalRoom.Register(user3) // user1 發送給全體 user1.Send("hi, I'm " + user1.GetName() + ".") // user2 發送給 user3 user2.SendTo(user3, "haha.") }
C語言簡版
#include <stdio.h> /** * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關係, * 將對象之間的通信封裝到一個中介者對象中,從而使得各個對象之間的關係更加鬆散。 * 在中介者模式中,對象之間不再直接相互交互,而是通過中介者來中轉消息。 */ typedef struct Colleague Colleague; typedef struct Mediator Mediator; // 定義抽象交互對象類 struct Colleague { int id; struct Mediator *mediator; void (*send)(struct Colleague *sender, char *message); void (*send_to)(struct Colleague *sender, Colleague *receiver, char *message); void (*receive)(struct Colleague *receiver, Colleague *sender, char *message); }; // 定義中介者類 struct Mediator { struct Colleague **colleagues; int colleagues_length; void (*send)(Colleague *sender, char *message); void (*send_to)(Colleague *sender, Colleague *receiver, char *message); }; // 交互對象發送消息 void colleague_send(Colleague *sender, char *message) { printf("\r\n colleague_send() [sender->id=%d message=%s]", sender->id, message); Mediator *mediator = sender->mediator; // 由中介者代為轉發消息給全體接收者 mediator->send(sender, message); } // 交互對象發送消息 void colleague_send_to(Colleague *sender, Colleague *receiver, char *message) { printf("\r\n colleague_send_to() [sender->id=%d receiver->id=%d message=%s]", sender->id, receiver->id, message); Mediator *mediator = sender->mediator; // 由中介者代為轉發消息給指定接收者 mediator->send_to(sender, receiver, message); } // 對象接收消息 void colleague_receive(Colleague *receiver, Colleague *sender, char *message) { printf("\r\n colleague_receive() [receiver->id=%d send->id=%d message=%s]", receiver->id, sender->id, message); } // 中介者發送消息 void mediator_send(Colleague *sender, char *message) { printf("\r\n mediator_send() [sender->id=%d message=%s]", sender->id, message); Colleague *receiver; for (int i = 0; i < sender->mediator->colleagues_length; i++) { // 中介者通知全體接收者 receiver = sender->mediator->colleagues[i]; receiver->receive(receiver, sender, message); } } // 中介者發送消息 void mediator_send_to(Colleague *sender, Colleague *receiver, char *message) { // 中介者通知指定接收者 printf("\r\n mediator_send_to() [sender->id=%d receiver->id=%d message=%s]", sender->id, receiver->id, message); receiver->receive(receiver, sender, message); } // 初始化交互對象類 void colleague_constructor(Colleague *self, int id) { self->id = id; self->send = colleague_send; self->send_to = colleague_send_to; self->receive = colleague_receive; } // 初始化中介者類 void mediator_constructor(Mediator *self, Colleague **colleagues, int colleagues_length) { self->colleagues = colleagues; self->colleagues_length = colleagues_length; // 給每個對象綁定中介者 for (int i = 0; i < self->colleagues_length; i++) { self->colleagues[i]->mediator = self; } self->send = &mediator_send; self->send_to = &mediator_send_to; } // test int main() { // 初始化具體交互對象a,分別綁定相關函數 Colleague colleague_a; colleague_constructor(&colleague_a, 1); // 初始化具體交互對象b,分別綁定相關函數 Colleague colleague_b; colleague_constructor(&colleague_b, 2); // 定義交互對象數組 Colleague *colleagues[] = {&colleague_a, &colleague_b}; int colleagues_length = sizeof(colleagues) / sizeof(colleagues[0]); printf("colleagues_length=%d", colleagues_length); // 初始化中介者類,綁定交互對象 Mediator mediator; mediator_constructor(&mediator, colleagues, colleagues_length); // 交互類發送消息 colleague_a.send(&colleague_a, "Hi, all! I'm a."); printf("\r\n ==== \r\n"); colleague_a.send_to(&colleague_a, &colleague_b, "Hello, colleague_b. I am a!"); printf("\r\n ==== \r\n"); colleague_b.send_to(&colleague_b, &colleague_a, "Hi, colleague_a! I'm b."); return 0; }
更多語言版本
不同語言實現設計模式:https://github.com/microwind/design-pattern