观察者模式指的是当存在一对多的场景的时候,一个对象发生了状态的变化之后,多个对象能够得到通知并且获得更新。
这个模式在一些pub/sub方式的中间件中很常见,例如消息的发布与订阅,MQTT的pub与sub。
但是如果真正的比较起来,跟pub/sub方式会存在一些区别,pub/sub的方式中,生产者和消费者中间还有一个broker,也就是说生产者和消费者之间是互相不知道的,生产者只负责生产数据给broker,而消费者只管去broker取数据。观察者模式的话,生产者在产生数据的时候,是会直接通知到消费者的
对于其中的产生变化的对象,我们可以把它称为生产者,而关注变化的对象,我们称为消费者。
在实际的场景中,该设计模式也是很常见。例如我们有 有一个服务是负责库存的,有好几个服务是会依赖库存的数据的,当库存产生数据的时候,他们需要被通知到,并且进行自己的业务处理。
java实现
在下面,我们会实现一个最简单的观察者模式的代码示例。主要包含三个文件,一个生产者,一个消费者以及一个测试类。
消费者
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class ObserverDemo { private String value; public void callback(String result) { System.out.println(result + " " + value); } public ObserverDemo(String value) { this.value = value; } }
|
我们在消费者里面实现一个callback方法,用来接收生产者发生变化的回调。
生产者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class ProducerDemo { private static Set<ObserverDemo> observerDemos = new HashSet<>(); private final static List<String> DAY = Arrays.asList("today", "tomorrow", "yesterday"); public static void addObserver(ObserverDemo observerDemo) { observerDemos.add(observerDemo); } public static void startProduce() throws InterruptedException { while (true) { String result = DAY.get(new Random().nextInt(DAY.size())); observerDemos.forEach(o -> o.callback(result)); Thread.sleep(2000); } } }
|
- 这里我们用一个set,存储所有的消费者。
- 当生产数据的时候,我们会通过调用消费者的callback函数,来实现对他们的通知。
测试代码
1 2 3 4 5 6 7 8
| public static void main(String[] args) throws Exception { ObserverDemo o1 = new ObserverDemo("morning"); ObserverDemo o2 = new ObserverDemo("afternoon"); ProducerDemo.addObserver(o1); ProducerDemo.addObserver(o2); ProducerDemo.startProduce(); }
|
- 这里我们新建两个消费者,通过赋予不同的值,来进行区分。
- 然后我们调用生产者的生产函数,来观察输出
结果

我们通过将观察者加入到生产者的通知队列中,然后在生产数据的时候,调用观察者的对应的回调函数,进而就不需要关心观察者的具体实现细节,并且实现了通知的功能,完成了代码之间的解耦。