中介者模式

简介

用一个中介对象来封装一系列的对象交互。

使用场景:

  • 聊天室

  • MVC架构的Controller

  • 机场调度系统

  • GUI对话框组件

实现要点:

  • 中介者协调所有同事对象

  • 同事对象只知道中介者

  • 降低对象间耦合

UML

代码示例

  1. 中介者接口,一个聊天室房间

public interface ChatRoomMediator {
    
    /**
     * 注册用户
     */
    void registerUser(User user);
    
    /**
     * 发送消息
     * @param message 消息内容
     * @param sender 发送者
     */
    void sendMessage(String message, User sender);
    
    /**
     * 发送私聊消息
     * @param message 消息内容
     * @param sender 发送者
     * @param receiver 接收者
     */
    void sendPrivateMessage(String message, User sender, User receiver);
}
  1. 中介者实现,具体的聊天室

public class ChatRoom implements ChatRoomMediator {
    
    private String roomName;
    private Map<String, User> users;
    private List<String> messageHistory;
    private DateTimeFormatter formatter;
    
    public ChatRoom(String roomName) {
        this.roomName = roomName;
        this.users = new HashMap<>();
        this.messageHistory = new ArrayList<>();
        this.formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
    }
    
    @Override
    public void registerUser(User user) {
        if (!users.containsKey(user.getName())) {
            users.put(user.getName(), user);
            user.setMediator(this);
            String joinMsg = "[系统] " + user.getName() + " 加入了聊天室";
            messageHistory.add(getTimestamp() + " " + joinMsg);
            System.out.println("✅ " + joinMsg);
            
            // 通知所有在线用户
            notifyAllUsers(joinMsg, user);
        }
    }
    
    @Override
    public void sendMessage(String message, User sender) {
        String timestamp = getTimestamp();
        String formattedMsg = String.format("[%s] %s: %s", 
                                          timestamp, sender.getName(), message);
        messageHistory.add(formattedMsg);
        
        System.out.println("💬 群聊消息: " + formattedMsg);
        
        // 发送给所有用户(除了发送者自己)
        for (User user : users.values()) {
            if (!user.equals(sender)) {
                user.receive(message, sender);
            }
        }
    }
    
    @Override
    public void sendPrivateMessage(String message, User sender, User receiver) {
        if (!users.containsValue(receiver)) {
            sender.receive("用户 " + receiver.getName() + " 不在聊天室", null);
            return;
        }
        
        String timestamp = getTimestamp();
        String formattedMsg = String.format("[%s] %s → %s (私聊): %s", 
                                          timestamp, sender.getName(), 
                                          receiver.getName(), message);
        messageHistory.add(formattedMsg);
        
        System.out.println("🔒 私聊消息: " + formattedMsg);
        
        // 只发送给接收者
        receiver.receive(message + " (私聊)", sender);
    }
    
    /**
     * 通知所有用户
     */
    private void notifyAllUsers(String systemMessage, User excludeUser) {
        for (User user : users.values()) {
            if (!user.equals(excludeUser)) {
                user.receive(systemMessage, null);
            }
        }
    }
    
    /**
     * 获取在线用户列表
     */
    public List<String> getOnlineUsers() {
        return new ArrayList<>(users.keySet());
    }
    
    /**
     * 获取消息历史
     */
    public List<String> getMessageHistory() {
        return new ArrayList<>(messageHistory);
    }
    
    /**
     * 获取时间戳
     */
    private String getTimestamp() {
        return LocalDateTime.now().format(formatter);
    }
    
    /**
     * 获取聊天室名称
     */
    public String getRoomName() {
        return roomName;
    }
    
    /**
     * 显示聊天室信息
     */
    public void showRoomInfo() {
        System.out.println("\n📱 ========== " + roomName + " ==========");
        System.out.println("在线用户数: " + users.size());
        System.out.println("在线用户: " + getOnlineUsers());
        System.out.println("消息数量: " + messageHistory.size());
        System.out.println("=======================================");
    }
}
  1. 用户抽象类,持有聊天室的引用

public abstract class User {
    
    protected String name;
    protected ChatRoomMediator mediator;
    
    public User(String name) {
        this.name = name;
    }
    
    /**
     * 设置中介者
     */
    public void setMediator(ChatRoomMediator mediator) {
        this.mediator = mediator;
    }
    
    /**
     * 发送消息(通过中介者)
     */
    public abstract void send(String message);
    
    /**
     * 发送私聊消息(通过中介者)
     */
    public abstract void sendPrivate(String message, User receiver);
    
    /**
     * 接收消息
     */
    public abstract void receive(String message, User sender);
    
    /**
     * 获取用户名
     */
    public String getName() {
        return name;
    }
}
  1. 具体的用户

//普通用户
public class RegularUser extends User {
    
    public RegularUser(String name) {
        super(name);
    }
    
    @Override
    public void send(String message) {
        System.out.println("👤 [" + name + "] 发送群聊: " + message);
        mediator.sendMessage(message, this);
    }
    
    @Override
    public void sendPrivate(String message, User receiver) {
        System.out.println("👤 [" + name + "] 发送私聊给 " + receiver.getName() + ": " + message);
        mediator.sendPrivateMessage(message, this, receiver);
    }
    
    @Override
    public void receive(String message, User sender) {
        if (sender == null) {
            // 系统消息
            System.out.println("  ← [" + name + "] 收到系统消息: " + message);
        } else {
            System.out.println("  ← [" + name + "] 收到来自 " + sender.getName() + " 的消息: " + message);
        }
    }
}
//VIP用户
public class VIPUser extends User {
    
    public VIPUser(String name) {
        super(name);
    }
    
    @Override
    public void send(String message) {
        System.out.println("👑 [VIP-" + name + "] 发送群聊: " + message);
        mediator.sendMessage(message, this);
    }
    
    @Override
    public void sendPrivate(String message, User receiver) {
        System.out.println("👑 [VIP-" + name + "] 发送私聊给 " + receiver.getName() + ": " + message);
        mediator.sendPrivateMessage(message, this, receiver);
    }
    
    @Override
    public void receive(String message, User sender) {
        if (sender == null) {
            // 系统消息
            System.out.println("  ← [VIP-" + name + "] 收到系统消息: " + message);
        } else {
            System.out.println("  ← [VIP-" + name + "] 收到来自 " + sender.getName() + " 的消息: " + message);
        }
    }
}

Last updated

Was this helpful?