Java设计模式 二十九 观察者模式 + 中介者模式

观察者模式 + 中介者模式

观察者模式中介者模式的结合能够创建一个高效的事件驱动系统,特别适合处理复杂的组件交互。在这种组合中,观察者模式负责事件的发布和订阅,而中介者模式负责协调和管理不同对象之间的交互。将这两种模式结合,可以实现更加清晰的解耦和更强的灵活性。


1. 场景说明

这两种模式的组合适用于以下场景:

  1. 需要协调多个组件之间的交互: 中介者模式作为中枢,管理各个对象之间的互动,同时利用观察者模式实现事件通知。
  2. 事件驱动的系统: 在复杂的事件驱动系统中,组件之间需要相互通知和响应,通过观察者模式来传递事件,通过中介者模式来协调响应。
  3. 解耦组件之间的直接依赖: 观察者模式解耦了事件发布者和订阅者,而中介者模式解耦了各个组件之间的直接联系,通过中介者来管理它们的交互。

2. 示例场景:聊天室系统

假设我们正在设计一个聊天室系统,其中:

  • 观察者模式用于处理消息的订阅和通知,每个用户(观察者)都可以订阅聊天消息(事件),并在新消息到来时接收通知。
  • 中介者模式用于管理聊天室中的用户之间的互动,所有消息的发送和接收都通过聊天室的中介者来协调,从而避免了用户之间的直接耦合。

(1) 观察者接口

定义一个观察者接口,表示接收消息的功能。

// 观察者接口:用于接收聊天消息
public interface ChatObserver {
    void receiveMessage(String message);  // 接收消息的方法
}

(2) 具体观察者

每个用户都是一个观察者,接收来自中介者的消息。

// 具体观察者:用户类
public class User implements ChatObserver {
    private String name;

    public User(String name) {
        this.name = name;
    }

    @Override
    public void receiveMessage(String message) {
        System.out.println(name + " 收到消息: " + message);
    }

    public String getName() {
        return name;
    }
}

(3) 中介者接口

定义一个中介者接口,负责协调聊天室内用户的消息交换。

// 中介者接口:管理用户之间的消息发送和接收
public interface ChatMediator {
    void sendMessage(String message, User user);
    void addUser(User user);  // 添加用户到聊天室
}

(4) 具体中介者:聊天室

聊天室是中介者的具体实现,负责管理所有用户并协调消息的发送。

// 具体中介者:聊天室
import java.util.ArrayList;
import java.util.List;

public class ChatRoomMediator implements ChatMediator {
    private List<User> users = new ArrayList<>();

    @Override
    public void sendMessage(String message, User user) {
        // 发送消息给聊天室中的所有用户,除了发送者
        for (User u : users) {
            if (u != user) {
                u.receiveMessage(message);
            }
        }
    }

    @Override
    public void addUser(User user) {
        users.add(user);
    }
}

(5) 客户端代码

客户端代码创建聊天室,并向其中添加用户。用户之间的消息通过聊天室中介者来传递。

public class Client {
    public static void main(String[] args) {
        // 创建聊天室
        ChatRoomMediator chatRoom = new ChatRoomMediator();

        // 创建用户并加入聊天室
        User user1 = new User("Alice");
        User user2 = new User("Bob");
        User user3 = new User("Charlie");

        chatRoom.addUser(user1);
        chatRoom.addUser(user2);
        chatRoom.addUser(user3);

        // 发送消息
        user1.receiveMessage("Alice: 你好,大家好!");
        chatRoom.sendMessage("Alice: 你好,大家好!", user1);

        System.out.println("\n");

        user2.receiveMessage("Bob: 你好,Alice!");
        chatRoom.sendMessage("Bob: 你好,Alice!", user2);

        System.out.println("\n");

        user3.receiveMessage("Charlie: 你好,Bob!");
        chatRoom.sendMessage("Charlie: 你好,Bob!", user3);
    }
}

运行结果:
Alice 收到消息: Alice: 你好,大家好!
Bob 收到消息: Alice: 你好,大家好!
Charlie 收到消息: Alice: 你好,大家好!

Bob 收到消息: Bob: 你好,Alice!
Alice 收到消息: Bob: 你好,Alice!
Charlie 收到消息: Bob: 你好,Alice!

Charlie 收到消息: Charlie: 你好,Bob!
Alice 收到消息: Charlie: 你好,Bob!
Bob 收到消息: Charlie: 你好,Bob!

3. 优点

观察者模式的优势:
  1. 松耦合: 观察者和被观察者之间解耦,允许系统中多个对象之间的事件通知而不直接依赖。
  2. 动态订阅: 观察者可以在运行时动态添加和移除,增强了系统的灵活性。
  3. 单一职责: 观察者只关注接收消息,不涉及消息的传播和协调,职责单一。
中介者模式的优势:
  1. 解耦: 中介者模式通过集中管理和协调对象间的交互,避免了对象之间的直接耦合,降低了系统的复杂度。
  2. 控制交互: 中介者模式为系统中的对象交互提供统一的控制入口,方便管理和修改交互行为。
  3. 扩展性: 通过修改中介者类,可以方便地扩展新的交互规则,而不需要修改各个对象的内部逻辑。
组合的优势:
  1. 解耦和集中管理: 观察者模式解耦了事件的发布和订阅,而中介者模式集中管理消息的流转,进一步解耦了对象间的复杂依赖关系。
  2. 灵活的事件通知机制: 观察者模式提供了灵活的消息通知机制,而中介者模式协调了多个观察者的行为,能够确保系统在变动时保持稳定。
  3. 提高可维护性: 中介者模式使得对象之间的交互被集中化,降低了直接依赖,使得系统更易于修改和维护。

4. 缺点

  1. 增加系统复杂性: 引入中介者和观察者会导致类和接口的增加,可能导致系统复杂度上升。
  2. 性能开销: 观察者模式可能涉及到大量的事件通知,系统在大量消息交换时可能出现性能瓶颈。
  3. 中介者过于复杂: 如果中介者处理的对象和交互过多,可能导致中介者类变得复杂,失去其简化交互的初衷。

5. 应用场景

  1. 聊天室系统: 中介者模式协调用户之间的互动,观察者模式用于实时消息推送。
  2. 事件驱动系统: 当多个模块需要响应同一事件时,可以使用观察者模式通知事件,使用中介者模式集中协调响应。
  3. GUI 事件处理: GUI 中的按钮、文本框等组件可以通过观察者模式处理用户事件,通过中介者模式协调各个组件的行为。
  4. 发布-订阅系统: 在多组件系统中,观察者模式用于处理事件的订阅和发布,而中介者模式用于管理多个组件之间的交互。

6. 总结

观察者模式 + 中介者模式的结合能够有效地解耦组件之间的关系,并实现复杂的事件驱动系统。观察者模式提供了一种灵活的事件通知机制,而中介者模式集中管理系统中各个对象的交互。两者结合能够让系统更具扩展性和可维护性,尤其适合需要协调多个组件交互的复杂场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十方来财

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值