Skip to content

中介

更新: 6/22/2025 字数: 0 字 时长: 0 分钟

定义

中介模式 (Mediator Pattern) 用一个中介对象来封装一系列对象之间的交互,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。它通过减少对象间混乱的依赖关系来限制对象间的直接通信。

角色

  • 中介者 (Mediator):定义对象间交互的接口
  • 具体中介者 (Concrete Mediator):实现中介者接口,协调各同事对象
  • 同事类 (Colleague):定义同事类的接口,维护中介者引用
  • 具体同事类 (Concrete Colleague):实现同事类接口,通过中介者与其他同事通信

实现

聊天室中介

java
// 中介者接口
public interface ChatMediator {
    void sendMessage(String msg, User user);
    void addUser(User user);
}

// 具体中介者:聊天室
public class ChatRoom implements ChatMediator {
    private List<User> users;
    
    public ChatRoom() {
        this.users = new ArrayList<>();
    }
    
    @Override
    public void addUser(User user) {
        this.users.add(user);
    }
    
    @Override
    public void sendMessage(String msg, User user) {
        for (User u : users) {
            // 消息不发送给发送者
            if (u != user) {
                u.receive(msg);
            }
        }
    }
}

// 同事类:用户
public abstract class User {
    protected ChatMediator mediator;
    protected String name;
    
    public User(ChatMediator med, String name) {
        this.mediator = med;
        this.name = name;
    }
    
    public abstract void send(String msg);
    public abstract void receive(String msg);
}

// 具体同事类:普通用户
public class BasicUser extends User {
    public BasicUser(ChatMediator med, String name) {
        super(med, name);
    }
    
    @Override
    public void send(String msg) {
        System.out.println(name + " 发送:" + msg);
        mediator.sendMessage(msg, this);
    }
    
    @Override
    public void receive(String msg) {
        System.out.println(name + " 收到:" + msg);
    }
}

// 具体同事类:管理员
public class AdminUser extends User {
    public AdminUser(ChatMediator med, String name) {
        super(med, name);
    }
    
    @Override
    public void send(String msg) {
        System.out.println("【管理员】" + name + " 广播:" + msg);
        mediator.sendMessage("【公告】" + msg, this);
    }
    
    @Override
    public void receive(String msg) {
        System.out.println("【管理员】" + name + " 收到:" + msg);
    }
}

// 客户端使用
public class ChatDemo {
    public static void main(String[] args) {
        ChatMediator mediator = new ChatRoom();
        
        User user1 = new BasicUser(mediator, "张三");
        User user2 = new BasicUser(mediator, "李四");
        User user3 = new BasicUser(mediator, "王五");
        User admin = new AdminUser(mediator, "管理员");
        
        mediator.addUser(user1);
        mediator.addUser(user2);
        mediator.addUser(user3);
        mediator.addUser(admin);
        
        user1.send("大家好!");
        admin.send("欢迎新用户加入!");
        user2.send("谢谢管理员!");
    }
}

机场交通控制中介

java
// 飞机接口
public interface Aircraft {
    void requestLanding();
    void landingComplete();
    void requestTakeoff();
    void takeoffComplete();
}

// 具体飞机
public class CommercialAircraft implements Aircraft {
    private String flightNumber;
    private AirTrafficControl atc;
    
    public CommercialAircraft(String flightNumber, AirTrafficControl atc) {
        this.flightNumber = flightNumber;
        this.atc = atc;
    }
    
    @Override
    public void requestLanding() {
        System.out.println(flightNumber + " 请求降落");
        atc.requestLanding(this);
    }
    
    @Override
    public void landingComplete() {
        System.out.println(flightNumber + " 降落完成");
        atc.notifyLandingComplete(this);
    }
    
    @Override
    public void requestTakeoff() {
        System.out.println(flightNumber + " 请求起飞");
        atc.requestTakeoff(this);
    }
    
    @Override
    public void takeoffComplete() {
        System.out.println(flightNumber + " 起飞完成");
        atc.notifyTakeoffComplete(this);
    }
}

// 中介者:空中交通管制
public interface AirTrafficControl {
    void requestLanding(Aircraft aircraft);
    void notifyLandingComplete(Aircraft aircraft);
    void requestTakeoff(Aircraft aircraft);
    void notifyTakeoffComplete(Aircraft aircraft);
}

// 具体中介者
public class ControlTower implements AirTrafficControl {
    private Queue<Aircraft> landingQueue = new LinkedList<>();
    private Queue<Aircraft> takeoffQueue = new LinkedList<>();
    private boolean runwayAvailable = true;
    
    @Override
    public void requestLanding(Aircraft aircraft) {
        if (runwayAvailable) {
            System.out.println("允许 " + aircraft + " 降落");
            runwayAvailable = false;
        } else {
            System.out.println("跑道占用," + aircraft + " 加入降落队列");
            landingQueue.add(aircraft);
        }
    }
    
    @Override
    public void notifyLandingComplete(Aircraft aircraft) {
        System.out.println(aircraft + " 已降落,跑道空闲");
        runwayAvailable = true;
        processNext();
    }
    
    @Override
    public void requestTakeoff(Aircraft aircraft) {
        if (runwayAvailable) {
            System.out.println("允许 " + aircraft + " 起飞");
            runwayAvailable = false;
        } else {
            System.out.println("跑道占用," + aircraft + " 加入起飞队列");
            takeoffQueue.add(aircraft);
        }
    }
    
    @Override
    public void notifyTakeoffComplete(Aircraft aircraft) {
        System.out.println(aircraft + " 已起飞,跑道空闲");
        runwayAvailable = true;
        processNext();
    }
    
    private void processNext() {
        // 优先处理降落请求
        if (!landingQueue.isEmpty()) {
            Aircraft next = landingQueue.poll();
            System.out.println("通知 " + next + " 降落");
            next.requestLanding();
        } else if (!takeoffQueue.isEmpty()) {
            Aircraft next = takeoffQueue.poll();
            System.out.println("通知 " + next + " 起飞");
            next.requestTakeoff();
        }
    }
}

// 使用示例
public class AirportDemo {
    public static void main(String[] args) {
        AirTrafficControl tower = new ControlTower();
        
        Aircraft flight1 = new CommercialAircraft("CA123", tower);
        Aircraft flight2 = new CommercialAircraft("UA456", tower);
        Aircraft flight3 = new CommercialAircraft("DL789", tower);
        
        // 飞行活动
        flight1.requestLanding();
        flight2.requestLanding();
        flight1.landingComplete();
        flight3.requestTakeoff();
        flight2.landingComplete();
        flight3.takeoffComplete();
    }
}

优缺点

优点:

  1. 减少类间依赖(从网状到星形)
  2. 简化对象协议
  3. 集中控制交互逻辑
  4. 提高系统灵活性
  5. 符合迪米特法则
  6. 便于扩展新同事类

缺点:

  1. 中介者可能变得复杂臃肿
  2. 可能成为系统性能瓶颈
  3. 过度集中化风险
  4. 增加系统复杂度
  5. 调试困难(交互逻辑集中)

应用场景

  1. 聊天应用程序
  2. 空中交通管制系统
  3. GUI 组件交互
  4. 分布式系统协调
  5. 工作流管理系统
  6. 多玩家游戏架构
  7. 企业应用集成

与其他模式的关系

  • 与观察者模式:常结合使用,中介者作为观察对象
  • 与门面模式:门面封装子系统,中介者协调同事
  • 与代理模式:中介者可代理同事间通信
  • 与命令模式:中介者发送命令给同事
  • 与状态模式:中介者状态影响协调行为
  • 与责任链模式:中介者替代责任链

JDK 中的中介模式

  1. Java Message Service (JMS)
  2. Java Executor 框架
  3. Java Timer 类
  4. Java Swing 中的 Mediator
  5. Spring 框架的事件机制
  6. Java EE Contexts and Dependency Injection (CDI)
  7. Java 并发工具包(java.util.concurrent)

注意事项

  1. 避免创建"上帝对象"
  2. 合理划分中介者职责
  3. 考虑中介者性能优化
  4. 设计清晰的通信协议
  5. 处理中介者单点故障
  6. 支持中介者链式处理
  7. 合理设计同事类接口

贡献者

The avatar of contributor named as LI SIR LI SIR
The avatar of contributor named as wkwbk wkwbk

页面历史