观察者模式(异步)

本文介绍了Java中的观察者模式,通过实例解析了如何创建被观察者和观察者,强调了在异步操作中避免阻塞主线程的重要性。文章还探讨了被观察者如何通知观察者并提供了相关源码分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

观察者模式(异步)

写在前面

  • 因为最近比较流行的RxJava\MVC\MVP\MVVM都跟一个叫做观察者模式的东东比较接近,当然这是作为Java开发者最熟悉不过的设计模式,因为在Java中已经默认为开发者实现了这种观察者模式。但是不自己理解的写一写还是收获甚微的
  • 在上一篇ReactiveX资料汇总中,我已经分享过一边外文的设计模式,在这在补充一下吧:https://en.wikipedia.org/wiki/Observer_pattern

  • 让我们来看看Java中是如何观察者模式的吧,来个实例先:

代码分析

import java.util.Observable;
import java.util.Scanner;

class EventSource extends Observable implements Runnable {
    public void run() {
        while (true) {
            String response = new Scanner(System.in).next();
            setChanged();
            notifyObservers(response);
        }
    }
}

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

public class MyApp {
    public static void main(String[] args) {
        System.out.println("Enter Text: ");
        EventSource eventSource = new EventSource();

        eventSource.addObserver(new Observer() {
            public void update(Observable obj, Object arg) {
                System.out.println("Received response: " + arg);
            }
        });

        new Thread(eventSource).start();
    }
}
  • 首先Java对外提供了简介的被观察者Observable类,想要设置被观察者的行为只要通过继承Observable类并在类的内部实现被观察者自己的行为即可,如果被观察者的操作是耗时操作,我们不能阻塞主线程所以在上面的例子中实现了Runable并在run中实现了自己的操作。
  • 当被观察者实现了自己操作的同时,这时候观察者并不知道,因为它采用的不是轮询机制(程序的噩梦),所以被观察者自身发生变化的时候它同时需要负责通知它的观察者,甚至可以具体到某个观察者这就是notifyObservers(params)中参数的作用
  • 观察者要做的事情很简单,就是就收到被观察者发来的通知作出相应的操作即可,所以在上面的例子中观察者只做了一件事那就是update,但是我们看到了被观察者是通过addObserver为自己关联上了观察者,那下面让我们看一下Observable源码,你就清楚被观察者的业务了,代码名称起得很规范无需多做解释:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package java.util;

import java.util.Observer;

public class Observable {
public Observable() {
    throw new RuntimeException("Stub!");
}

public synchronized void addObserver(Observer o) {
    throw new RuntimeException("Stub!");
}

public synchronized void deleteObserver(Observer o) {
    throw new RuntimeException("Stub!");
}

public void notifyObservers() {
    throw new RuntimeException("Stub!");
}

public void notifyObservers(Object arg) {
    throw new RuntimeException("Stub!");
}

public synchronized void deleteObservers() {
    throw new RuntimeException("Stub!");
}

protected synchronized void setChanged() {
    throw new RuntimeException("Stub!");
}

protected synchronized void clearChanged() {
    throw new RuntimeException("Stub!");
}

public synchronized boolean hasChanged() {
    throw new RuntimeException("Stub!");
}

public synchronized int countObservers() {
    throw new RuntimeException("Stub!");
}
}
  • 顺便把观察者的接口源码页贴上吧,这样就是完整的Observer Pattern了

package java.util;

import java.util.Observable;

public interface Observer {
void update(Observable var1, Object var2);
}

总结

  • 观察者模式Observer Pattern又叫发布订阅模式Publish/Subscrible,同时里面含有被观察者Subject和观察者Observer两种角色,所以看RxJava和Rxtrofit里面各种眼花缭乱的命名规则,总有种想骂娘的冲动好吧我又浅薄了。。。
  • 被观察者除了要完成自己的基本业务的同时还要负责同时某个或者全部的关心它状态的观察者,传达它的当前状态
  • 设计模式只是比较好的编程讨论,他千变万化不要拘泥于它表面的形式

Java观察者模式可以异步实现,具体实现方式如下: 1. 定义观察者接口,其中包含更新方法(update)。 ``` public interface Observer { void update(Object obj); } ``` 2. 定义被观察者(主题)类,其中包含添加观察者、删除观察者通知观察者的方法。通知观察者的时候,可以使用Java线程池来实现异步通知。 ``` import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Subject { private List<Observer> observers; private ExecutorService executorService; public Subject() { observers = new ArrayList<>(); executorService = Executors.newFixedThreadPool(10); } public void addObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } public void notifyObservers(Object obj) { for (Observer observer : observers) { executorService.execute(() -> { observer.update(obj); }); } } } ``` 3. 定义观察者类,实现观察者接口的更新方法。 ``` public class ConcreteObserver implements Observer { private String name; public ConcreteObserver(String name) { this.name = name; } @Override public void update(Object obj) { System.out.println(name + " received message: " + obj); } } ``` 4. 测试异步通知。 ``` public class Test { public static void main(String[] args) { Subject subject = new Subject(); Observer observer1 = new ConcreteObserver("Observer1"); Observer observer2 = new ConcreteObserver("Observer2"); subject.addObserver(observer1); subject.addObserver(observer2); subject.notifyObservers("Hello, world!"); } } ``` 上述代码中,我们新建了一个Java线程池(executorService)来实现异步通知,通知消息是"Hello, world!"。当调用notifyObservers方法时,程序会遍历所有观察者,将更新方法放入线程池中执行,实现异步通知。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值