设计模式-中介者模式详解

中介者模式详解

目录

  1. 中介者模式简介
  2. 核心流程
  3. 重难点分析
  4. Spring中的源码分析
  5. 具体使用场景
  6. 面试高频点
  7. 使用总结

中介者模式简介

定义

中介者模式(Mediator Pattern)是一种行为型设计模式,它用一个中介对象来封装一系列对象之间的交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

核心思想

  • 解耦对象交互:通过中介者解耦对象之间的直接依赖关系
  • 集中控制:将对象间的交互逻辑集中到中介者中
  • 简化通信:简化对象之间的通信方式
  • 易于维护:交互逻辑的修改只需要修改中介者

模式结构

  • Mediator(抽象中介者):定义同事对象到中介者对象的接口
  • ConcreteMediator(具体中介者):实现抽象中介者,协调各同事对象的交互关系
  • Colleague(抽象同事类):定义各同事对象的公有接口
  • ConcreteColleague(具体同事类):实现抽象同事类,通过中介者与其他同事对象通信

核心流程

中介者模式流程图

消息处理 同事对象层次 中介者层次 消息接收 消息解析 消息路由 消息转发 抽象同事类 具体同事A 具体同事B 具体同事C 抽象中介者接口 具体中介者实现 同事对象注册表 客户端 创建中介者 创建同事对象 注册同事对象到中介者 同事对象发送消息 中介者接收消息 中介者处理消息 中介者转发消息给目标同事 目标同事接收消息 目标同事处理消息 返回处理结果

基本实现流程

1. 定义抽象中介者
java 复制代码
// 抽象中介者
public abstract class Mediator {
    protected List<Colleague> colleagues = new ArrayList<>();
  
    public void register(Colleague colleague) {
        colleagues.add(colleague);
        colleague.setMediator(this);
    }
  
    public void unregister(Colleague colleague) {
        colleagues.remove(colleague);
        colleague.setMediator(null);
    }
  
    public abstract void notify(Colleague sender, String message);
    public abstract void notify(Colleague sender, String message, Colleague target);
}
2. 定义抽象同事类
java 复制代码
// 抽象同事类
public abstract class Colleague {
    protected Mediator mediator;
    protected String name;
  
    public Colleague(String name) {
        this.name = name;
    }
  
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
  
    public String getName() {
        return name;
    }
  
    public abstract void send(String message);
    public abstract void send(String message, Colleague target);
    public abstract void receive(String message, Colleague sender);
}
3. 实现具体中介者
java 复制代码
// 具体中介者
public class ConcreteMediator extends Mediator {
    @Override
    public void notify(Colleague sender, String message) {
        System.out.println("中介者转发消息: " + sender.getName() + " -> " + message);
        for (Colleague colleague : colleagues) {
            if (colleague != sender) {
                colleague.receive(message, sender);
            }
        }
    }
  
    @Override
    public void notify(Colleague sender, String message, Colleague target) {
        System.out.println("中介者转发消息: " + sender.getName() + " -> " + target.getName() + " : " + message);
        if (colleagues.contains(target)) {
            target.receive(message, sender);
        }
    }
}
4. 实现具体同事类
java 复制代码
// 具体同事类A
public class ConcreteColleagueA extends Colleague {
    public ConcreteColleagueA(String name) {
        super(name);
    }
  
    @Override
    public void send(String message) {
        System.out.println(name + " 发送广播消息: " + message);
        mediator.notify(this, message);
    }
  
    @Override
    public void send(String message, Colleague target) {
        System.out.println(name + " 发送私聊消息给 " + target.getName() + ": " + message);
        mediator.notify(this, message, target);
    }
  
    @Override
    public void receive(String message, Colleague sender) {
        System.out.println(name + " 收到来自 " + sender.getName() + " 的消息: " + message);
    }
}

// 具体同事类B
public class ConcreteColleagueB extends Colleague {
    public ConcreteColleagueB(String name) {
        super(name);
    }
  
    @Override
    public void send(String message) {
        System.out.println(name + " 发送广播消息: " + message);
        mediator.notify(this, message);
    }
  
    @Override
    public void send(String message, Colleague target) {
        System.out.println(name + " 发送私聊消息给 " + target.getName() + ": " + message);
        mediator.notify(this, message, target);
    }
  
    @Override
    public void receive(String message, Colleague sender) {
        System.out.println(name + " 收到来自 " + sender.getName() + " 的消息: " + message);
    }
}
5. 客户端使用
java 复制代码
public class Client {
    public static void main(String[] args) {
        // 创建中介者
        Mediator mediator = new ConcreteMediator();
      
        // 创建同事对象
        Colleague colleagueA = new ConcreteColleagueA("同事A");
        Colleague colleagueB = new ConcreteColleagueB("同事B");
      
        // 注册同事对象到中介者
        mediator.register(colleagueA);
        mediator.register(colleagueB);
      
        // 发送消息
        colleagueA.send("大家好,我是同事A");
        colleagueB.send("你好,我是同事B");
        colleagueA.send("你好", colleagueB);
    }
}

重难点分析

重难点1:中介者的复杂度管理

问题描述

随着同事对象数量的增加,中介者可能变得过于复杂,难以维护。

解决方案
java 复制代码
// 分层中介者模式
public abstract class BaseMediator {
    protected Map<String, Colleague> colleagues = new HashMap<>();
  
    public void register(String key, Colleague colleague) {
        colleagues.put(key, colleague);
        colleague.setMediator(this);
    }
  
    public Colleague getColleague(String key) {
        return colleagues.get(key);
    }
  
    public abstract void notify(String senderKey, String message);
    public abstract void notify(String senderKey, String message, String targetKey);
}

// 具体中介者实现
public class ChatMediator extends BaseMediator {
    @Override
    public void notify(String senderKey, String message) {
        Colleague sender = getColleague(senderKey);
        if (sender != null) {
            System.out.println("广播消息: " + sender.getName() + " -> " + message);
            for (Colleague colleague : colleagues.values()) {
                if (colleague != sender) {
                    colleague.receive(message, sender);
                }
            }
        }
    }
  
    @Override
    public void notify(String senderKey, String message, String targetKey) {
        Colleague sender = getColleague(senderKey);
        Colleague target = getColleague(targetKey);
        if (sender != null && target != null) {
            System.out.println("私聊消息: " + sender.getName() + " -> " + target.getName() + " : " + message);
            target.receive(message, sender);
        }
    }
}

// 使用策略模式的中介者
public class StrategyMediator extends BaseMediator {
    private Map<String, MessageStrategy> strategies = new HashMap<>();
  
    public void addStrategy(String messageType, MessageStrategy strategy) {
        strategies.put(messageType, strategy);
    }
  
    @Override
    public void notify(String senderKey, String message) {
        Colleague sender = getColleague(senderKey);
        if (sender != null) {
            String messageType = extractMessageType(message);
            MessageStrategy strategy = strategies.get(messageType);
            if (strategy != null) {
                strategy.handleMessage(sender, message, colleagues);
            } else {
                // 默认处理
                defaultHandleMessage(sender, message);
            }
        }
    }
  
    private String extractMessageType(String message) {
        // 根据消息内容提取类型
        if (message.startsWith("@")) {
            return "PRIVATE";
        } else if (message.startsWith("#")) {
            return "GROUP";
        }
        return "BROADCAST";
    }
  
    private void defaultHandleMessage(Colleague sender, String message) {
        System.out.println("默认处理: " + sender.getName() + " -> " + message);
    }
}

重难点2:中介者的性能优化

问题描述

中介者可能成为性能瓶颈,特别是在高并发场景下。

解决方案
java 复制代码
// 异步中介者
public class AsyncMediator extends BaseMediator {
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    private final BlockingQueue<MessageTask> messageQueue = new LinkedBlockingQueue<>();
  
    public AsyncMediator() {
        // 启动消息处理线程
        executor.submit(new MessageProcessor());
    }
  
    @Override
    public void notify(String senderKey, String message) {
        messageQueue.offer(new MessageTask(senderKey, message, null));
    }
  
    @Override
    public void notify(String senderKey, String message, String targetKey) {
        messageQueue.offer(new MessageTask(senderKey, message, targetKey));
    }
  
    private class MessageProcessor implements Runnable {
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    MessageTask task = messageQueue.take();
                    processMessage(task);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
    }
  
    private void processMessage(MessageTask task) {
        Colleague sender = getColleague(task.getSenderKey());
        if (sender != null) {
            if (task.getTargetKey() != null) {
                Colleague target = getColleague(task.getTargetKey());
                if (target != null) {
                    target.receive(task.getMessage(), sender);
                }
            } else {
                for (Colleague colleague : colleagues.values()) {
                    if (colleague != sender) {
                        colleague.receive(task.getMessage(), sender);
                    }
                }
            }
        }
    }
  
    public void shutdown() {
        executor.shutdown();
    }
}

// 消息任务类
public class MessageTask {
    private final String senderKey;
    private final String message;
    private final String targetKey;
  
    public MessageTask(String senderKey, String message, String targetKey) {
        this.senderKey = senderKey;
        this.message = message;
        this.targetKey = targetKey;
    }
  
    // getter方法
    public String getSenderKey() { return senderKey; }
    public String getMessage() { return message; }
    public String getTargetKey() { return targetKey; }
}

重难点3:中介者的扩展性

问题描述

如何让中介者模式具有良好的扩展性,支持新的同事对象类型。

解决方案
java 复制代码
// 可扩展的中介者
public class ExtensibleMediator extends BaseMediator {
    private final Map<Class<?>, List<Colleague>> colleaguesByType = new HashMap<>();
    private final Map<String, MediatorPlugin> plugins = new HashMap<>();
  
    @Override
    public void register(String key, Colleague colleague) {
        super.register(key, colleague);
      
        // 按类型分组
        Class<?> colleagueType = colleague.getClass();
        colleaguesByType.computeIfAbsent(colleagueType, k -> new ArrayList<>()).add(colleague);
      
        // 通知插件
        for (MediatorPlugin plugin : plugins.values()) {
            plugin.onColleagueRegistered(colleague);
        }
    }
  
    public void addPlugin(String name, MediatorPlugin plugin) {
        plugins.put(name, plugin);
        plugin.initialize(this);
    }
  
    public void removePlugin(String name) {
        MediatorPlugin plugin = plugins.remove(name);
        if (plugin != null) {
            plugin.destroy();
        }
    }
  
    public <T extends Colleague> List<T> getColleaguesByType(Class<T> type) {
        List<Colleague> colleagues = colleaguesByType.get(type);
        if (colleagues != null) {
            return colleagues.stream()
                    .map(type::cast)
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
}

// 中介者插件接口
public interface MediatorPlugin {
    void initialize(ExtensibleMediator mediator);
    void onColleagueRegistered(Colleague colleague);
    void onMessageSent(Colleague sender, String message, Colleague target);
    void destroy();
}

// 日志插件
public class LoggingPlugin implements MediatorPlugin {
    private ExtensibleMediator mediator;
  
    @Override
    public void initialize(ExtensibleMediator mediator) {
        this.mediator = mediator;
    }
  
    @Override
    public void onColleagueRegistered(Colleague colleague) {
        System.out.println("同事注册: " + colleague.getName());
    }
  
    @Override
    public void onMessageSent(Colleague sender, String message, Colleague target) {
        System.out.println("消息发送: " + sender.getName() + " -> " + 
                         (target != null ? target.getName() : "所有人") + " : " + message);
    }
  
    @Override
    public void destroy() {
        System.out.println("日志插件销毁");
    }
}

重难点4:中介者的测试

问题描述

如何对中介者模式进行单元测试,确保交互逻辑的正确性。

解决方案
java 复制代码
// 可测试的中介者
public class TestableMediator extends BaseMediator {
    private final List<MessageEvent> messageEvents = new ArrayList<>();
  
    @Override
    public void notify(String senderKey, String message) {
        Colleague sender = getColleague(senderKey);
        if (sender != null) {
            messageEvents.add(new MessageEvent(sender, message, null, MessageType.BROADCAST));
          
            for (Colleague colleague : colleagues.values()) {
                if (colleague != sender) {
                    colleague.receive(message, sender);
                }
            }
        }
    }
  
    @Override
    public void notify(String senderKey, String message, String targetKey) {
        Colleague sender = getColleague(senderKey);
        Colleague target = getColleague(targetKey);
        if (sender != null && target != null) {
            messageEvents.add(new MessageEvent(sender, message, target, MessageType.PRIVATE));
            target.receive(message, sender);
        }
    }
  
    public List<MessageEvent> getMessageEvents() {
        return new ArrayList<>(messageEvents);
    }
  
    public void clearMessageEvents() {
        messageEvents.clear();
    }
}

// 消息事件类
public class MessageEvent {
    private final Colleague sender;
    private final String message;
    private final Colleague target;
    private final MessageType type;
    private final long timestamp;
  
    public MessageEvent(Colleague sender, String message, Colleague target, MessageType type) {
        this.sender = sender;
        this.message = message;
        this.target = target;
        this.type = type;
        this.timestamp = System.currentTimeMillis();
    }
  
    // getter方法
    public Colleague getSender() { return sender; }
    public String getMessage() { return message; }
    public Colleague getTarget() { return target; }
    public MessageType getType() { return type; }
    public long getTimestamp() { return timestamp; }
}

// 消息类型枚举
public enum MessageType {
    BROADCAST, PRIVATE, GROUP
}

// 单元测试
public class MediatorTest {
    @Test
    public void testBroadcastMessage() {
        TestableMediator mediator = new TestableMediator();
        Colleague colleagueA = new ConcreteColleagueA("A");
        Colleague colleagueB = new ConcreteColleagueB("B");
      
        mediator.register("A", colleagueA);
        mediator.register("B", colleagueB);
      
        colleagueA.send("Hello");
      
        List<MessageEvent> events = mediator.getMessageEvents();
        assertEquals(1, events.size());
        assertEquals("A", events.get(0).getSender().getName());
        assertEquals("Hello", events.get(0).getMessage());
        assertEquals(MessageType.BROADCAST, events.get(0).getType());
    }
  
    @Test
    public void testPrivateMessage() {
        TestableMediator mediator = new TestableMediator();
        Colleague colleagueA = new ConcreteColleagueA("A");
        Colleague colleagueB = new ConcreteColleagueB("B");
      
        mediator.register("A", colleagueA);
        mediator.register("B", colleagueB);
      
        colleagueA.send("Hello", colleagueB);
      
        List<MessageEvent> events = mediator.getMessageEvents();
        assertEquals(1, events.size());
        assertEquals("A", events.get(0).getSender().getName());
        assertEquals("B", events.get(0).getTarget().getName());
        assertEquals("Hello", events.get(0).getMessage());
        assertEquals(MessageType.PRIVATE, events.get(0).getType());
    }
}

Spring中的源码分析

Spring的ApplicationContext作为中介者

java 复制代码
// ApplicationContext接口
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
  
    String getId();
    String getApplicationName();
    String getDisplayName();
    long getStartupDate();
    ApplicationContext getParent();
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
    BeanFactory getParentBeanFactory();
    boolean containsLocalBean(String name);
    String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
    void publishEvent(ApplicationEvent event);
    void publishEvent(Object event);
}

Spring的ApplicationEventPublisher

java 复制代码
// ApplicationEventPublisher接口
@FunctionalInterface
public interface ApplicationEventPublisher {
    default void publishEvent(ApplicationEvent event) {
        publishEvent((Object) event);
    }
  
    void publishEvent(Object event);
}

// AbstractApplicationContext中的实现
public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {
  
    private ApplicationEventMulticaster applicationEventMulticaster;
  
    @Override
    public void publishEvent(ApplicationEvent event) {
        publishEvent(event, null);
    }
  
    @Override
    public void publishEvent(Object event) {
        publishEvent(event, null);
    }
  
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
      
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent) event;
        } else {
            applicationEvent = new PayloadApplicationEvent<>(this, event);
        }
      
        if (this.earlyApplicationEvents != null) {
            this.earlyApplicationEvents.add(applicationEvent);
        } else {
            getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
        }
      
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
            } else {
                this.parent.publishEvent(event);
            }
        }
    }
}

Spring的ApplicationEventMulticaster

java 复制代码
// ApplicationEventMulticaster接口
public interface ApplicationEventMulticaster {
    void addApplicationListener(ApplicationListener<?> listener);
    void addApplicationListenerBean(String listenerBeanName);
    void removeApplicationListener(ApplicationListener<?> listener);
    void removeApplicationListenerBean(String listenerBeanName);
    void removeAllListeners();
    void multicastEvent(ApplicationEvent event);
    void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}

// SimpleApplicationEventMulticaster实现
public class SimpleApplicationEventMulticaster implements ApplicationEventMulticaster {
  
    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor();
      
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }
  
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void invokeListener(ApplicationListener listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                listener.onApplicationEvent(event);
            } catch (Throwable err) {
                errorHandler.handleError(err);
            }
        } else {
            listener.onApplicationEvent(event);
        }
    }
}

Spring的ApplicationListener

java 复制代码
// ApplicationListener接口
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E event);
}

// 使用示例
@Component
public class UserEventListener implements ApplicationListener<UserRegisteredEvent> {
  
    @Override
    public void onApplicationEvent(UserRegisteredEvent event) {
        System.out.println("用户注册事件: " + event.getUsername());
        // 处理用户注册逻辑
    }
}

// 事件类
public class UserRegisteredEvent extends ApplicationEvent {
    private final String username;
    private final String email;
  
    public UserRegisteredEvent(Object source, String username, String email) {
        super(source);
        this.username = username;
        this.email = email;
    }
  
    public String getUsername() { return username; }
    public String getEmail() { return email; }
}

具体使用场景

1. 聊天室系统

java 复制代码
// 聊天室中介者
public class ChatRoomMediator {
    private final Map<String, User> users = new HashMap<>();
    private final List<ChatMessage> messages = new ArrayList<>();
  
    public void addUser(User user) {
        users.put(user.getId(), user);
        user.setMediator(this);
        broadcastSystemMessage(user.getName() + " 加入了聊天室");
    }
  
    public void removeUser(String userId) {
        User user = users.remove(userId);
        if (user != null) {
            user.setMediator(null);
            broadcastSystemMessage(user.getName() + " 离开了聊天室");
        }
    }
  
    public void sendMessage(String senderId, String message) {
        User sender = users.get(senderId);
        if (sender != null) {
            ChatMessage chatMessage = new ChatMessage(sender, message, System.currentTimeMillis());
            messages.add(chatMessage);
            broadcastMessage(chatMessage);
        }
    }
  
    public void sendPrivateMessage(String senderId, String receiverId, String message) {
        User sender = users.get(senderId);
        User receiver = users.get(receiverId);
        if (sender != null && receiver != null) {
            ChatMessage chatMessage = new ChatMessage(sender, message, System.currentTimeMillis());
            receiver.receiveMessage(chatMessage);
        }
    }
  
    private void broadcastMessage(ChatMessage message) {
        for (User user : users.values()) {
            if (user != message.getSender()) {
                user.receiveMessage(message);
            }
        }
    }
  
    private void broadcastSystemMessage(String message) {
        ChatMessage systemMessage = new ChatMessage(null, "[系统] " + message, System.currentTimeMillis());
        for (User user : users.values()) {
            user.receiveMessage(systemMessage);
        }
    }
}

// 用户类
public class User {
    private final String id;
    private final String name;
    private ChatRoomMediator mediator;
  
    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }
  
    public void setMediator(ChatRoomMediator mediator) {
        this.mediator = mediator;
    }
  
    public void sendMessage(String message) {
        if (mediator != null) {
            mediator.sendMessage(id, message);
        }
    }
  
    public void sendPrivateMessage(String receiverId, String message) {
        if (mediator != null) {
            mediator.sendPrivateMessage(id, receiverId, message);
        }
    }
  
    public void receiveMessage(ChatMessage message) {
        System.out.println(name + " 收到消息: " + message.getContent());
    }
  
    // getter方法
    public String getId() { return id; }
    public String getName() { return name; }
}

// 聊天消息类
public class ChatMessage {
    private final User sender;
    private final String content;
    private final long timestamp;
  
    public ChatMessage(User sender, String content, long timestamp) {
        this.sender = sender;
        this.content = content;
        this.timestamp = timestamp;
    }
  
    // getter方法
    public User getSender() { return sender; }
    public String getContent() { return content; }
    public long getTimestamp() { return timestamp; }
}

2. 飞机控制系统

java 复制代码
// 飞机控制中介者
public class AirTrafficControlMediator {
    private final Map<String, Aircraft> aircrafts = new HashMap<>();
    private final List<Runway> runways = new ArrayList<>();
    private final List<Gate> gates = new ArrayList<>();
  
    public void registerAircraft(Aircraft aircraft) {
        aircrafts.put(aircraft.getId(), aircraft);
        aircraft.setMediator(this);
    }
  
    public void requestLanding(String aircraftId) {
        Aircraft aircraft = aircrafts.get(aircraftId);
        if (aircraft != null) {
            Runway availableRunway = findAvailableRunway();
            if (availableRunway != null) {
                availableRunway.setOccupied(true);
                aircraft.land(availableRunway);
                System.out.println("飞机 " + aircraftId + " 被分配到跑道 " + availableRunway.getId());
            } else {
                aircraft.waitForRunway();
                System.out.println("飞机 " + aircraftId + " 需要等待可用跑道");
            }
        }
    }
  
    public void requestTakeoff(String aircraftId) {
        Aircraft aircraft = aircrafts.get(aircraftId);
        if (aircraft != null) {
            Runway availableRunway = findAvailableRunway();
            if (availableRunway != null) {
                availableRunway.setOccupied(true);
                aircraft.takeoff(availableRunway);
                System.out.println("飞机 " + aircraftId + " 从跑道 " + availableRunway.getId() + " 起飞");
            } else {
                aircraft.waitForRunway();
                System.out.println("飞机 " + aircraftId + " 需要等待可用跑道");
            }
        }
    }
  
    public void requestGate(String aircraftId) {
        Aircraft aircraft = aircrafts.get(aircraftId);
        if (aircraft != null) {
            Gate availableGate = findAvailableGate();
            if (availableGate != null) {
                availableGate.setOccupied(true);
                aircraft.park(availableGate);
                System.out.println("飞机 " + aircraftId + " 被分配到登机口 " + availableGate.getId());
            } else {
                aircraft.waitForGate();
                System.out.println("飞机 " + aircraftId + " 需要等待可用登机口");
            }
        }
    }
  
    private Runway findAvailableRunway() {
        return runways.stream()
                .filter(runway -> !runway.isOccupied())
                .findFirst()
                .orElse(null);
    }
  
    private Gate findAvailableGate() {
        return gates.stream()
                .filter(gate -> !gate.isOccupied())
                .findFirst()
                .orElse(null);
    }
}

// 飞机类
public class Aircraft {
    private final String id;
    private final String type;
    private AirTrafficControlMediator mediator;
  
    public Aircraft(String id, String type) {
        this.id = id;
        this.type = type;
    }
  
    public void setMediator(AirTrafficControlMediator mediator) {
        this.mediator = mediator;
    }
  
    public void requestLanding() {
        if (mediator != null) {
            mediator.requestLanding(id);
        }
    }
  
    public void requestTakeoff() {
        if (mediator != null) {
            mediator.requestTakeoff(id);
        }
    }
  
    public void requestGate() {
        if (mediator != null) {
            mediator.requestGate(id);
        }
    }
  
    public void land(Runway runway) {
        System.out.println("飞机 " + id + " 降落在跑道 " + runway.getId());
    }
  
    public void takeoff(Runway runway) {
        System.out.println("飞机 " + id + " 从跑道 " + runway.getId() + " 起飞");
    }
  
    public void park(Gate gate) {
        System.out.println("飞机 " + id + " 停靠在登机口 " + gate.getId());
    }
  
    public void waitForRunway() {
        System.out.println("飞机 " + id + " 等待可用跑道");
    }
  
    public void waitForGate() {
        System.out.println("飞机 " + id + " 等待可用登机口");
    }
  
    // getter方法
    public String getId() { return id; }
    public String getType() { return type; }
}

3. 订单处理系统

java 复制代码
// 订单处理中介者
public class OrderProcessingMediator {
    private final Map<String, Order> orders = new HashMap<>();
    private final List<OrderProcessor> processors = new ArrayList<>();
    private final List<OrderObserver> observers = new ArrayList<>();
  
    public void registerProcessor(OrderProcessor processor) {
        processors.add(processor);
        processor.setMediator(this);
    }
  
    public void registerObserver(OrderObserver observer) {
        observers.add(observer);
    }
  
    public void processOrder(Order order) {
        orders.put(order.getId(), order);
        notifyObservers("订单创建", order);
      
        for (OrderProcessor processor : processors) {
            if (processor.canProcess(order)) {
                processor.process(order);
                break;
            }
        }
    }
  
    public void updateOrderStatus(String orderId, OrderStatus status) {
        Order order = orders.get(orderId);
        if (order != null) {
            order.setStatus(status);
            notifyObservers("订单状态更新", order);
        }
    }
  
    private void notifyObservers(String event, Order order) {
        for (OrderObserver observer : observers) {
            observer.onOrderEvent(event, order);
        }
    }
}

// 订单类
public class Order {
    private final String id;
    private final String customerId;
    private final List<OrderItem> items;
    private OrderStatus status;
    private final long createTime;
  
    public Order(String id, String customerId, List<OrderItem> items) {
        this.id = id;
        this.customerId = customerId;
        this.items = items;
        this.status = OrderStatus.PENDING;
        this.createTime = System.currentTimeMillis();
    }
  
    // getter和setter方法
    public String getId() { return id; }
    public String getCustomerId() { return customerId; }
    public List<OrderItem> getItems() { return items; }
    public OrderStatus getStatus() { return status; }
    public void setStatus(OrderStatus status) { this.status = status; }
    public long getCreateTime() { return createTime; }
}

// 订单处理器接口
public interface OrderProcessor {
    void setMediator(OrderProcessingMediator mediator);
    boolean canProcess(Order order);
    void process(Order order);
}

// 库存验证处理器
public class InventoryValidator implements OrderProcessor {
    private OrderProcessingMediator mediator;
  
    @Override
    public void setMediator(OrderProcessingMediator mediator) {
        this.mediator = mediator;
    }
  
    @Override
    public boolean canProcess(Order order) {
        return order.getStatus() == OrderStatus.PENDING;
    }
  
    @Override
    public void process(Order order) {
        System.out.println("验证订单库存: " + order.getId());
        // 验证库存逻辑
        if (validateInventory(order)) {
            mediator.updateOrderStatus(order.getId(), OrderStatus.CONFIRMED);
        } else {
            mediator.updateOrderStatus(order.getId(), OrderStatus.CANCELLED);
        }
    }
  
    private boolean validateInventory(Order order) {
        // 模拟库存验证
        return true;
    }
}

// 支付处理器
public class PaymentProcessor implements OrderProcessor {
    private OrderProcessingMediator mediator;
  
    @Override
    public void setMediator(OrderProcessingMediator mediator) {
        this.mediator = mediator;
    }
  
    @Override
    public boolean canProcess(Order order) {
        return order.getStatus() == OrderStatus.CONFIRMED;
    }
  
    @Override
    public void process(Order order) {
        System.out.println("处理订单支付: " + order.getId());
        // 支付处理逻辑
        if (processPayment(order)) {
            mediator.updateOrderStatus(order.getId(), OrderStatus.PAID);
        } else {
            mediator.updateOrderStatus(order.getId(), OrderStatus.PAYMENT_FAILED);
        }
    }
  
    private boolean processPayment(Order order) {
        // 模拟支付处理
        return true;
    }
}

面试高频点

面试知识点思维导图

中介者模式面试点 基本概念 实现方式 重难点 Spring应用 设计原则 实际应用 解耦对象交互 集中控制 简化通信 易于维护 Mediator抽象中介者 ConcreteMediator具体中介者 Colleague抽象同事类 ConcreteColleague具体同事类 复杂度管理 性能优化 扩展性 测试 ApplicationContext ApplicationEventPublisher ApplicationEventMulticaster ApplicationListener 单一职责 开闭原则 依赖倒置 接口隔离 聊天室系统 飞机控制系统 订单处理系统 事件系统

1. 中介者模式的基本概念

问题:什么是中介者模式?

答案要点:

  • 用一个中介对象来封装一系列对象之间的交互
  • 使各对象不需要显式地相互引用,从而使其耦合松散
  • 属于行为型设计模式
  • 可以独立地改变它们之间的交互
问题:中介者模式有哪些角色?

答案要点:

  • Mediator(抽象中介者):定义同事对象到中介者对象的接口
  • ConcreteMediator(具体中介者):实现抽象中介者,协调各同事对象的交互关系
  • Colleague(抽象同事类):定义各同事对象的公有接口
  • ConcreteColleague(具体同事类):实现抽象同事类,通过中介者与其他同事对象通信

2. 实现方式相关

问题:如何实现中介者模式?

答案要点:

java 复制代码
// 1. 定义抽象中介者
public abstract class Mediator {
    protected List<Colleague> colleagues = new ArrayList<>();
  
    public void register(Colleague colleague) {
        colleagues.add(colleague);
        colleague.setMediator(this);
    }
  
    public abstract void notify(Colleague sender, String message);
}

// 2. 定义抽象同事类
public abstract class Colleague {
    protected Mediator mediator;
  
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
  
    public abstract void send(String message);
    public abstract void receive(String message, Colleague sender);
}

// 3. 实现具体中介者
public class ConcreteMediator extends Mediator {
    @Override
    public void notify(Colleague sender, String message) {
        for (Colleague colleague : colleagues) {
            if (colleague != sender) {
                colleague.receive(message, sender);
            }
        }
    }
}

3. 重难点问题

问题:中介者模式与观察者模式的区别?

答案要点:

  • 目的:中介者模式是协调对象交互,观察者模式是通知状态变化
  • 关系:中介者模式是一对多,观察者模式是一对多
  • 耦合度:中介者模式耦合度更高,观察者模式耦合度更低
  • 使用场景:中介者模式用于复杂交互,观察者模式用于状态通知
问题:如何解决中介者的复杂度问题?

答案要点:

java 复制代码
// 1. 分层中介者
public class LayeredMediator {
    private final Map<String, Mediator> mediators = new HashMap<>();
  
    public void addMediator(String layer, Mediator mediator) {
        mediators.put(layer, mediator);
    }
  
    public void notify(String layer, Colleague sender, String message) {
        Mediator mediator = mediators.get(layer);
        if (mediator != null) {
            mediator.notify(sender, message);
        }
    }
}

// 2. 使用策略模式
public class StrategyMediator {
    private final Map<String, MessageStrategy> strategies = new HashMap<>();
  
    public void addStrategy(String messageType, MessageStrategy strategy) {
        strategies.put(messageType, strategy);
    }
  
    public void notify(Colleague sender, String message) {
        String messageType = extractMessageType(message);
        MessageStrategy strategy = strategies.get(messageType);
        if (strategy != null) {
            strategy.handleMessage(sender, message);
        }
    }
}

4. Spring中的应用

问题:Spring中如何使用中介者模式?

答案要点:

java 复制代码
// 1. 使用ApplicationEventPublisher
@Component
public class OrderService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
  
    public void createOrder(Order order) {
        // 创建订单逻辑
        eventPublisher.publishEvent(new OrderCreatedEvent(order));
    }
}

// 2. 使用ApplicationListener
@Component
public class OrderEventListener implements ApplicationListener<OrderCreatedEvent> {
    @Override
    public void onApplicationEvent(OrderCreatedEvent event) {
        // 处理订单创建事件
        System.out.println("订单创建: " + event.getOrder().getId());
    }
}

5. 设计原则相关

问题:中介者模式体现了哪些设计原则?

答案要点:

  • 单一职责:中介者只负责协调对象交互
  • 开闭原则:可以添加新的同事对象而不修改现有代码
  • 依赖倒置:依赖抽象而不是具体实现
  • 接口隔离:客户端只依赖需要的接口

6. 实际应用场景

问题:中介者模式适用于哪些场景?

答案要点:

  • 聊天室系统:用户之间的消息传递
  • 飞机控制系统:飞机与塔台之间的通信
  • 订单处理系统:订单处理流程的协调
  • 事件系统:事件发布和订阅
  • GUI系统:界面组件之间的交互

使用总结

中介者模式的优势

  1. 解耦:减少对象之间的直接依赖关系
  2. 集中控制:将交互逻辑集中到中介者中
  3. 简化通信:简化对象之间的通信方式
  4. 易于维护:交互逻辑的修改只需要修改中介者

中介者模式的缺点

  1. 复杂度增加:中介者可能变得过于复杂
  2. 性能问题:中介者可能成为性能瓶颈
  3. 学习成本:需要理解中介者模式的概念
  4. 过度设计:简单场景可能不需要使用

使用建议

  1. 复杂交互:只用于复杂的对象交互场景
  2. 性能考虑:注意中介者的性能影响
  3. 扩展性:考虑中介者的扩展性设计
  4. 测试:做好中介者的单元测试

最佳实践

  1. 分层设计:使用分层中介者避免复杂度
  2. 策略模式:使用策略模式处理不同类型的消息
  3. 异步处理:使用异步处理提高性能
  4. 插件机制:使用插件机制提高扩展性
  5. 单元测试:为中介者编写完整的单元测试

与其他模式的对比

  1. 与观察者模式:中介者模式是协调交互,观察者模式是状态通知
  2. 与命令模式:中介者模式是协调对象,命令模式是封装请求
  3. 与策略模式:中介者模式是协调策略,策略模式是算法选择

中介者模式是一种有用的行为型设计模式,特别适用于需要协调复杂对象交互、集中控制交互逻辑、简化对象通信等场景。通过合理使用中介者模式,可以大大提高系统的可维护性和可扩展性。

相关推荐
bkspiderx4 小时前
C++设计模式之创建型模式:建造者模式(Builder)
c++·设计模式·建造者模式
大飞pkz5 小时前
【设计模式】单例模式
开发语言·单例模式·设计模式·c#·单例模式懒汉式·单例模式饿汉式
yujkss7 小时前
23种设计模式之【中介者模式】-核心原理与 Java 实践
java·设计模式·中介者模式
易元4 天前
模式组合应用-享元模式
后端·设计模式
vker4 天前
第 2 天:工厂方法模式(Factory Method Pattern)—— 创建型模式
java·后端·设计模式
vker5 天前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
晨米酱6 天前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机6 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机6 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言