在java开发中,要实现事件驱动,即当发生按特定事件时,通知关联方以便作出改变,有三种方案:

一、分析对比

1、观察者模式;

2、Redis 订阅机制;

3、专业版 MQ。

下面逐一进行介绍并总结其各自的适用场景。

1. Java 观察者模式(Observer Pattern)

这是设计模式层面的一种行为型模式,核心是实现「一对多」的对象依赖关系:当一个对象(被观察者 / Subject)状态发生变化时,所有依赖它的对象(观察者 / Observer)会被自动通知并更新。

核心特点:
  • 内存内同步通信:观察者和被观察者都运行在同一个 JVM 进程内,通知是同步的(被观察者通知完所有观察者后,自身方法才会返回)。
  • 耦合度低:基于接口编程(Subject/Observer 接口),观察者和被观察者只需依赖接口,无需知道对方具体实现。
  • 无持久化 / 重试:通知过程仅在内存中完成,若观察者处理失败,被观察者不会重试,也无消息持久化能力。

简单代码示例:

import java.util.Observable;
import java.util.Observer;

// 被观察者:发布消息的对象
class MessageSubject extends Observable {
    public void publishMessage(String msg) {
        // 标记状态变化
        setChanged();
        // 通知所有观察者
        notifyObservers(msg);
    }
}

// 观察者1:接收并处理消息
class MessageObserver1 implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("观察者1收到消息:" + arg);
    }
}

// 观察者2:接收并处理消息
class MessageObserver2 implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("观察者2收到消息:" + arg);
    }
}

// 测试
public class ObserverDemo {
    public static void main(String[] args) {
        MessageSubject subject = new MessageSubject();
        // 注册观察者
        subject.addObserver(new MessageObserver1());
        subject.addObserver(new MessageObserver2());
        // 发布消息
        subject.publishMessage("Hello 观察者模式");
    }
}

输出

观察者2收到消息:Hello 观察者模式

观察者1收到消息:Hello 观察者模式

从中可以看出消息的处理顺序是随机的。

2. Redis 订阅 / 发布机制(Pub/Sub)

Redis 提供的轻量级消息通信机制,核心是「频道(Channel)」:发布者向指定频道发送消息,所有订阅该频道的客户端都会收到消息。

核心特点:
  • 跨进程 / 跨机器通信:基于 Redis 服务端中转,支持不同进程、不同机器的客户端通信。
  • 无持久化 / 无确认机制:消息发送后若没有订阅者,消息直接丢失;Redis 不会记录消息,也不保证订阅者一定收到(如客户端断连)。
  • 轻量简单:无需复杂配置,适合低可靠性要求的场景(如实时通知、状态同步)。

简单使用示例(Redis CLI):

# 终端1:订阅频道 "news"
redis-cli SUBSCRIBE news

# 终端2:向频道 "news" 发布消息
redis-cli PUBLISH news "Redis 发布订阅测试"

# 终端1 会收到:
# "message"
# "news"
# "Redis 发布订阅测试"
3. 专业版 MQ(以 RabbitMQ 为例)

RabbitMQ 是基于 AMQP 协议的重量级消息中间件,核心是「消息队列」:消息由生产者发送到队列,消费者从队列获取消息,中间件提供完善的消息管控能力。

核心特点:
  • 高可靠性:支持消息持久化(磁盘存储)、消息确认(ACK)、重试机制,确保消息不丢失。
  • 异步解耦:生产者发送消息后无需等待消费者处理,中间件缓存消息,消费者按需消费。
  • 丰富的路由策略:支持交换机(Direct/Fanout/Topic)、队列绑定,可实现复杂的消息路由(如按规则分发给不同消费者)。
  • 集群 / 高可用:支持集群部署,避免单点故障,适合高并发、高可靠性要求的生产环境。
简单代码示例(Java + RabbitMQ):
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class RabbitMQDemo {
    private static final String QUEUE_NAME = "test_queue";

    // 生产者:发送消息
    public static void sendMessage() throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // Redis 服务地址
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            // 声明队列(持久化)
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            String message = "RabbitMQ 测试消息";
            // 发送消息
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println("生产者发送消息:" + message);
        }
    }

    // 消费者:接收消息
    public static void receiveMessage() throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        System.out.println("消费者等待接收消息...");

        // 消息回调处理
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println("消费者收到消息:" + message);
            // 手动确认消息已处理(确保不重复消费)
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };
        // 消费消息(关闭自动确认)
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {});
    }

    public static void main(String[] args) throws Exception {
        // 启动生产者
        sendMessage();
        // 启动消费者
        receiveMessage();
    }
}

二、三者核心对比

维度 Java 观察者模式 Redis 订阅 / 发布 RabbitMQ(专业 MQ)
通信范围 单 JVM 进程内 跨进程 / 跨机器 跨进程 / 跨机器
可靠性 无重试 / 无持久化 无重试 / 无持久化 有重试 / 有持久化 / ACK
耦合度 低(接口解耦) 极低(Redis 中转) 极低(队列解耦)
性能 极高(内存通信) 高(Redis 轻量) 中(功能复杂)
适用场景 单进程内状态通知 轻量实时通知、低可靠 高并发、高可靠业务场景
核心定位 设计模式(代码层面) 轻量消息工具 企业级消息中间件

三、总结

  1. Java 观察者模式是「代码层面」的解耦方案,仅适用于单进程内的消息通知,无跨进程能力;
  2. Redis 订阅机制是「轻量跨进程」的消息工具,适合低可靠性要求的实时通知,不适合核心业务;
  3. RabbitMQ 等专业 MQ 是「企业级」的消息中间件,提供完善的可靠性保障,是核心业务异步解耦、削峰填谷的首选。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。