Java 源码解读 - 观察者模式

本文详细解读了Java中观察者模式的实现原理。被观察者通过extends Observable并使用addObserver方法添加观察者,然后通过setChanged和notifyObservers通知更新。观察者则需implements Observer并实现update方法。源码中,被观察者维护了一个Observer类型的List,通过notifyObservers按注册顺序调用观察者的update方法。文章还探讨了如何添加、删除观察者以及更新标志的管理。

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

JDK 封装好的原生的观察者模式,使用起来很简单,只需要

  1. 被观察者 extends Observable,使用 addObserver(Observer observer) 添加观察者,使用 setChange() + notifityObservers(Object data) 通知更新
  2. 观察者 implements Observer,实现 update(Observable observable, Object data) 方法即可

源码也很简单,我们通过源码了解其机制:

观察者:

package java.util;


/**
 * {@code Observer} is the interface to be implemented by objects that
 * receive notification of updates on an {@code Observable} object.
 *
 * @see Observable
 */
public interface Observer {

    /**
     * This method is called if the specified {@code Observable} object's
     * {@code notifyObservers} method is called (because the {@code Observable}
     * object has been updated.
     *
     * @param observable
     *            the {@link Observable} object.
     * @param data
     *            the data passed to {@link Observable#notifyObservers(Object)}.
     */
    void update(Observable observable, Object data);
}

是一个接口,有一个方法接收更新,更新的参数是产生更新的被观察者 Observable 和更新发出的信息 Object

被观察者:

package java.util;

/**
 * Observable is used to notify a group of Observer objects when a change
 * occurs. On creation, the set of observers is empty. After a change occurred,
 * the application can call the {@link #notifyObservers()} method. This will
 * cause the invocation of the {@code update()} method of all registered
 * Observers. The order of invocation is not specified. This implementation will
 * call the Observers in the order they registered. Subclasses are completely
 * free in what order they call the update methods.
 *
 * @see Observer
 */

上面意思是被观察者用于在变化发生时通知一组观察者对象。
在创建被观察者时,是没有观察者的,需要通过注册(addObserver(Observer observer))。
通过 notifyObservers() 调用所有注册(获得了引用)的观察者的 update() 方法。
调用没有特定次序,会按照观察者的注册顺序调用。子类可以重写 notifyObservers() 按自定义次序更新。

public class Observable {

List<Observer> observers = new ArrayList<Observer>();

boolean changed = false;

/**
 * Constructs a new {@code Observable} object.
 */
public Observable() {
}

/**
 * Adds the specified observer to the list of observers. If it is already
 * registered, it is not added a second time.
 *
 * @param observer
 *            the Observer to add.
 */
public void addObserver(Observer observer) {
    if (observer == null) {
        throw new NullPointerException("observer == null");
    }
    synchronized (this) {
        if (!observers.contains(observer))
            observers.add(observer);
    }
}

observers:声明 Observer 类型的 List 用于存放注册的 Observer
changed:
无参构造函数用以生成被观察者
addObserver():添加观察者,判断如果为空,抛出空对象异常;使用 synchronized(this) {} 上锁,使用同步方式添加,能保证不会二次添加;使用 contains() 方法判断对象是否已经注册过

/**
 * Clears the changed flag for this {@code Observable}. After calling
 * {@code clearChanged()}, {@code hasChanged()} will return {@code false}.
 */
protected void clearChanged() {
    changed = false;
}

/**
 * Returns the number of observers registered to this {@code Observable}.
 *
 * @return the number of observers.
 */
public int countObservers() {
    return observers.size();
}

/**
 * Removes the specified observer from the list of observers. Passing null
 * won't do anything.
 *
 * @param observer
 *            the observer to remove.
 */
public synchronized void deleteObserver(Observer observer) {
    observers.remove(observer);
}

/**
 * Removes all observers from the list of observers.
 */
public synchronized void deleteObservers() {
    observers.clear();
}

clearChanged():设更新标志为 false,清除更新
countObservers():返回 List 的长度
deleteObserver():移除 List 中指定的观察者
deleteObservers():清空 List 中所有观察者

/**
 * Returns the changed flag for this {@code Observable}.
 *
 * @return {@code true} when the changed flag for this {@code Observable} is
 *         set, {@code false} otherwise.
 */
public boolean hasChanged() {
    return changed;
}

/**
 * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
 * method for every observer in the list of observers using null as the
 * argument. Afterwards, calls {@code clearChanged()}.
 * <p>
 * Equivalent to calling {@code notifyObservers(null)}.
 */
public void notifyObservers() {
    notifyObservers(null);
}

/**
 * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
 * method for every Observer in the list of observers using the specified
 * argument. Afterwards calls {@code clearChanged()}.
 *
 * @param data
 *            the argument passed to {@code update()}.
 */
@SuppressWarnings("unchecked")
public void notifyObservers(Object data) {
    int size = 0;
    Observer[] arrays = null;
    synchronized (this) {
        if (hasChanged()) {
            clearChanged();
            size = observers.size();
            arrays = new Observer[size];
            observers.toArray(arrays);
        }
    }
    if (arrays != null) {
        for (Observer observer : arrays) {
            observer.update(this, data);
        }
    }
}

/**
 * Sets the changed flag for this {@code Observable}. After calling
 * {@code setChanged()}, {@code hasChanged()} will return {@code true}.
 */
protected void setChanged() {
    changed = true;
}

hasChanged():返回更新标志,用以保证更新时通知

notifyObservers():调用 notifyObservers(null) 方法,没有数据传输
notifyObservers(Oject data):当 hasChanged() 为 true 时,进入通知逻辑:一、使用 clearChanged() 清除这次更新;二、将 List 转化为 array 数组,这是为了使用 for(Oject object: arrays) 对注册的观察者进行遍历,效率比较高效;三、使用 update() 传递 Oject 或空值进行数据传输

setChanged():通知时要使用 setChanged() 使更新标志生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值