Java设计模式之观察者模式

419 阅读2分钟

概念

在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。

观察者模式主要有两个角色

  • Subject 观察主题对象,也可以叫被观察或者被订阅对象
  • Observer 观察者或者订阅者对象,当Subject有变动,就会通知到每一个Observer

我们按照定牛奶的方式来理解,Subject实际上可以理解成奶厂,Observer可以理解成为我们每个用户,而观察者模式就是在Subject发生变化的时候,去通知每一个Observer对象,以达到消息通知目的。

在这里插入图片描述 这是从别人博客中直接拿的图(blog.csdn.net/chengyuqian…

自己实现一个观察者模式

定义观察者主题对象

/**
 * 观察者主题对象
 */
public interface Subject {

    /**
     * 订阅操作
     */
    void attach(Observer observer);

    /**
     * 取消订阅操作
     */
    void detach(Observer observer);

    /**
     * 通知变动
     */
    void notifyChanged();
}

定义观察者观察人对象

/**
  * 观察者订阅人对象
  */
 public interface Observer {

     /**
      * 接收变动通知
      */
     void update();
 }

分别创建SubjectObserver对象的实现类

public static class RealSubject implements Subject {

private List<Observer> observerList = new ArrayList<>();

@Override
public void attach(Observer observer) {
    observerList.add(observer);
}

@Override
public void detach(Observer observer) {
    observerList.remove(observer);
}

@Override
public void notifyChanged() {
    for (Observer observer : observerList) {
        observer.update();
    }
}

}

public static class RealObject implements Observer {
    @Override
    public void update() {
        System.out.println("接收到了通知");
    }
}

Observer的实现可以是很多个,可以理解为平时一家奶厂,订奶用户肯定是有很多个。 调用实现

public static void main(String[] args) {
    Subject subject = new RealSubject();
    Observer observer = new RealObject();
    subject.attach(observer);
    subject.notifyChanged();
}

使用Java自带的观察者模式类实现

上面自己通过接口的方式,实现了一个观察者模式,但是Java自身也是有这方面的实现了,下面看看如何用Java自带的实现一个观察者模式

public static class RealSubject extends Observable {

    public void makeChanged() {
        setChanged();
        notifyObservers();
    }
}

public static class RealObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("调用了-->");
    }
}

public static void main(String[] args) {
    RealSubject subject = new RealSubject();
    RealObserver observer = new RealObserver();
    subject.addObserver(observer);
    subject.makeChanged();
}

调用的基本逻辑是一样的。Java已经帮我们把订阅和取消订阅操作都封装了起来,通知也进行了封装,并且进行了同步处理。只要需要注意的是,这里有个setChanged();,在发生变化之后,必须调用这个方法告诉发生了改变,否则不会正常处理消息的。

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)   //这里的标志位就是setChanged处理的标志位
            return;
        arrLocal = obs.toArray();
        clearChanged();
    }

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

好了,观察者模式就到这里了。