目录
- 中介者模式
- 中介者模式结构
- 中介者模式适用场景
- 中介者模式优缺点
- 练手题目
- 题目描述
- 输入描述
- 输出描述
- 题解
中介者模式
中介者模式是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。
中介者模式结构
-
组件 (Component) 是各种包含业务逻辑的类。 每个组件都有一个指向中介者的引用, 该引用被声明为中介者接口类型。 组件不知道中介者实际所属的类, 因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。
-
中介者 (Mediator) 接口声明了与组件交流的方法, 但通常仅包括一个通知方法。 组件可将任意上下文 (包括自己的对象) 作为该方法的参数, 只有这样接收组件和发送者类之间才不会耦合。
-
具体中介者 (Concrete Mediator) 封装了多种组件间的关系。 具体中介者通常会保存所有组件的引用并对其进行管理, 甚至有时会对其生命周期进行管理。
-
组件并不知道其他组件的情况。 如果组件内发生了重要事件, 它只能通知中介者。 中介者收到通知后能轻易地确定发送者, 这或许已足以判断接下来需要触发的组件了。
对于组件来说, 中介者看上去完全就是一个黑箱。 发送者不知道最终会由谁来处理自己的请求, 接收者也不知道最初是谁发出了请求。
中介者模式通用代码:
//抽象中介者
abstract class Mediator{//定义同事类protected List<Colleague> colleagues = new ArrayList<>();public void addColleague(Colleague colleague){colleagues.add(colleague); }public abstract void sendMessage(String message,Colleague sender);
}//具体中介类,一般只有一个。
class ConcreteMediator extends Mediator{@Overridepublic void sendMessage(String message, Colleague sender) {for (Colleague colleague : colleagues) {if (colleague != sender) {colleague.receiveMessage(message);}}}
}//抽象同事类
abstract class Colleague{protected Mediator mediator;public Colleague(Mediator mediator){this.mediator = mediator;mediator.addColleague(this);
}public abstract void sendMessage(String name);public abstract void receiveMessage(String message);
}// 具体同事类1
class ConcreteColleague1 extends Colleague {public ConcreteColleague1(Mediator mediator) {super(mediator);}@Overridepublic void sendMessage(String message) {System.out.println("Colleague1 sends: " + message);mediator.sendMessage(message, this);}@Overridepublic void receiveMessage(String message) {System.out.println("Colleague1 received: " + message);}
}// 具体同事类2
class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator mediator) {super(mediator);}@Overridepublic void sendMessage(String message) {System.out.println("Colleague2 sends: " + message);mediator.sendMessage(message, this);}@Overridepublic void receiveMessage(String message) {System.out.println("Colleague2 received: " + message);}
}
中介者模式适用场景
-
当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。
该模式让你将对象间的所有关系抽取成为一个单独的类, 以使对于特定组件的修改工作独立于其他组件。
-
当组件因过于依赖其他组件而无法在不同应用中复用时, 可使用中介者模式。
应用中介者模式后, 每个组件不再知晓其他组件的情况。 尽管这些组件无法直接交流, 但它们仍可通过中介者对象进行间接交流。 如果你希望在不同应用中复用一个组件, 则需要为其提供一个新的中介者类。
-
如果为了能在不同情景下复用一些基本行为, 导致你需要被迫创建大量组件子类时, 可使用中介者模式。
由于所有组件间关系都被包含在中介者中, 因此你无需修改组件就能方便地新建中介者类以定义新的组件合作方式。
中介者模式优缺点
中介者模式优点:
-
单一职责原则。 你可以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。
-
开闭原则。 你无需修改实际组件就能增加新的中介者。
-
你可以减轻应用中多个组件间的耦合情况。
-
你可以更方便地复用各个组件。
中介者模式缺点:
- 中介者会膨胀得很大,逻辑复杂。一段时间后,可能会演化为上帝对象。
练手题目
题目描述
小明正在设计一个简单的多人聊天室系统,有多个用户和一个聊天室中介者,用户通过中介者进行聊天,请你帮他完成这个系统的设计。
输入描述
第一行包括一个整数N,表示用户的数量(1 <= N <= 100) 第二行是N个用户,比如User1 User2 User3,用空格分隔 第三行开始,每行包含两个字符串,表示消息的发出者和消息内容,用空格分隔
输出描述
对于每个用户,输出一行,包含该用户收到的所有消息内容。
题解
初始解法:
import java.util.*;// 抽象中介者类
abstract class Mediator {protected List<Colleague> colleagues = new ArrayList<>();// 添加同事到列表public void addColleague(Colleague colleague) {colleagues.add(colleague);}// 抽象方法:发送消息public abstract void sendMessage(String name, String message, Colleague sender);
}// 具体中介者类
class ConcreteMediator extends Mediator {// 实现发送消息方法@Overridepublic void sendMessage(String name, String message, Colleague sender) {// 遍历所有同事,将消息发送给除了发送者之外的所有人for (Colleague c : colleagues) {if (c != sender) {c.receiveMessage(name, message);}}}
}// 抽象同事类
abstract class Colleague {protected Mediator mediator;protected String name;// 构造函数public Colleague(String name, Mediator mediator) {this.name = name;this.mediator = mediator;mediator.addColleague(this);}// 抽象方法:发送消息public abstract void sendMessage(String message);// 抽象方法:接收消息public abstract void receiveMessage(String senderName, String message);
}// 具体同事类
class ConcreteColleague extends Colleague {public ConcreteColleague(String name, Mediator mediator) {super(name, mediator);}// 实现发送消息方法@Overridepublic void sendMessage(String message) {mediator.sendMessage(this.name, message, this);}// 实现接收消息方法@Overridepublic void receiveMessage(String senderName, String message) {System.out.println(this.name + " received: " + message);}
}// 主类
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取用户数量int n = scanner.nextInt();scanner.nextLine(); // 读取用户名String[] users = scanner.nextLine().split(" ");// 创建中介者Mediator mediator = new ConcreteMediator();// 创建用于存储同事对象的映射Map<String, Colleague> colleagues = new HashMap<>();// 创建所有用户的同事对象for (String user : users) {colleagues.put(user, new ConcreteColleague(user, mediator));}// 读取并处理消息while (scanner.hasNextLine()) {String line = scanner.nextLine();String[] parts = line.split(" ", 2);if (parts.length < 2) break;String senderName = parts[0];String message = parts[1];// 获取发送者并发送消息Colleague sender = colleagues.get(senderName);if (sender != null) {sender.sendMessage(message);}}scanner.close();}
}
优化后:
import java.util.*;// 中介者接口
interface Mediator {void sendMessage(String message, String sender);void addUser(User user);
}// 具体中介者
class ChatMediator implements Mediator {private List<User> users = new ArrayList<>();@Overridepublic void sendMessage(String message, String sender) {for (User user : users) {if (!user.getName().equals(sender)) {user.receive(message); }}}@Overridepublic void addUser(User user) {users.add(user);}
}// 用户接口
interface User {void send(String message);void receive(String message);String getName();
}// 具体用户
class ChatUser implements User {private String name;private Mediator mediator;public ChatUser(String name, Mediator mediator) {this.name = name;this.mediator = mediator;mediator.addUser(this);}@Overridepublic void send(String message) {mediator.sendMessage(message, this.name);}@Overridepublic void receive(String message) {System.out.println(this.name + " received: " + message);}@Overridepublic String getName() {return this.name;}
}public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Mediator mediator = new ChatMediator();Map<String, User> users = new HashMap<>();int n = scanner.nextInt();scanner.nextLine(); String[] userNames = scanner.nextLine().split(" ");for (String name : userNames) {users.put(name, new ChatUser(name, mediator));}while (scanner.hasNextLine()) {String line = scanner.nextLine();String[] parts = line.split(" ", 2);if (parts.length < 2) break;String sender = parts[0];String message = parts[1];User user = users.get(sender);if (user != null) {user.send(message);}}scanner.close();}
}