JAVA内置的观察者模式

定义观察者模式
观察者模式定义了对象之间的一对多的依赖,这样依赖,当一个对象改变状态时,它的所依赖者都会受到通知并自动更新。
比如说,当我们订阅今日头条的时候,头条会推送新闻给我们,并且是推送给所有的订阅用户,而且是无序推送的!
这里的今日头条就是subject,而咱们所有的订阅者就是对应的观察者,这是存在着一对多的关系

回到主题:我们来看看java内置的观察者模式是什么样子的

/**
 * An observable object can have one or more observers. An observer
 * may be any object that implements interface <tt>Observer</tt>. After an
 * observable instance changes, an application calling the
 * <code>Observable</code>'s <code>notifyObservers</code> method
 * causes all of its observers to be notified of the change by a call
 * to their <code>update</code> method.
 * 
 * The order in which notifications will be delivered is unspecified.
 * The default implementation provided in the Observable class will
 * notify Observers in the order in which they registered interest, but
 * subclasses may change this order, use no guaranteed order, deliver
 * notifications on separate threads, or may guarantee that their
 * subclass follows this order, as they choose.
 * 
 * Note that this notification mechanism is has nothing to do with threads
 * and is completely separate from the <tt>wait</tt> and <tt>notify</tt>
 * mechanism of class <tt>Object</tt>.
 * 
 * When an observable object is newly created, its set of observers is
 * empty. Two observers are considered the same if and only if the
 * <tt>equals</tt> method returns true for them.
 *
 */

我来用我蹩脚的英文把这段内容核心翻译一下:
1,一个主题可以有多个观察者,观察者要实现Observer接口。之后主题变量发生改变时,会调用Observable’s notifyObservers方法,通知所有的已经注册的观察者要更新信息了,此时观察者要调用各自的update方法来更新内容。
2,当主题通知所有依赖他的观察者时,通知的顺序是无序的。默认的顺序是观察者在主题中注册的顺序。子类可以根据自己的需求来改变通知观察者的顺序。
3,需要注意的是,这里通知机制和线程中的wait方法和notify方法一点关系都没有,请不要搞混了。
4,当被观察主题新建时,注册的观察者为空。


接下来,我们来看看Observable类

private boolean changed = false;
    private Vector obs;
    public Observable() {
        obs = new Vector();
    }

注解:有两个类变量,一个是changed,此变量定义主题是否发生改变;obs是个vector变量,用于存放注册的观察者
此类只有一个无参构造函数


 public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
             public void notifyObservers() {
              notifyObservers(null);
    }
     obs.addElement(o); } }

注解:这是一个使用synchronized修饰的添加观察者方法,并且有一个判断此前是否该观察者注册过,以保证集合是没有重复的观察者


 public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

注解:同样使用了synchronized修饰的删除观察者的方法,如果传入参数为null的时候,对这个方法将毫无影响!


 public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
            /* We don't want the Observer doing callbacks into
             * arbitrary code while holding its own Monitor.
             * The code where we extract each Observable from
             * the Vector and store the state of the Observer
             * needs synchronization, but notifying observers
             * does not (should not).  The worst result of any
             * potential race-condition here is that:
             * 1) a newly-added Observer will miss a
             *   notification in progress
             * 2) a recently unregistered Observer will be
             *   wrongly notified when it doesn't care
             */
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

注解:通知观察者更新的方法,这个方法首先是检查changed的值,如果没有改变过这个变量,则直接返回不会通知注册的观察者
如果确实调用过setChanged方法,则首先将changed值初始化,然后通知所有已经注册的观察调用本身的uodate方法,执行的顺序类似于栈,先注册的观察者后通知更新


public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

注解:清空注册表的名单,此时注册表为空


protected synchronized void setChanged() {
        changed = true;
    }

注解:标记此时主题的变量发生改变


protected synchronized void clearChanged() {
        changed = false;
    }

注解:清楚改变,也可以理解为初始化changed值


public synchronized boolean hasChanged() {
        return changed;
    }

注解:判断主题变量是否发生了改变


 public synchronized int countObservers() {
        return obs.size();
    }

注解:返回主题中注册的观察者数量


java.util.Observable的黑暗面
可观察者是一个类,而不是一个接口,甚至没有实现一个接口。首先因为Observable是一个类,你必须设计一个类去实现他,如果某个类想要同时具有Observable类和另一个超类的行为,就会陷入尴尬的局面,毕竟java不支持多重继承。


java中既然有观察者模式,怎么能没有观察者呢?
观察者闪亮登场!

public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

注解:当你想要注册为观察者的时候,你就得实现观察者接口进而获得主题更新时的信息。



总结观察者模式:
1,观察者模式定义了对象之间一对多的关系
2,主题也就是可观察者用一个共同的接口来实现更新观察者(java内置的观察者模式违背了这一条)
3,观察者和主题之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口
4,在多个观察者时,不可以依赖特定的通知次序
5,java中有多重观察者模式的实现,包括通用的java.util.Observable
6,要注意java.util.Obserable实现上带来的一些问题
7,如果有必要,自己实现观察者模式
8,Swing大量使用了观察者模式,许多GUI框架也是如此

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Narasimha_Karumanchi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值