前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >观察者模式浅析

观察者模式浅析

作者头像
孟君
发布2019-09-03 18:24:57
4190
发布2019-09-03 18:24:57
举报
文章被收录于专栏:孟君的编程札记

观察者模式是一种对象行为型模式,其意图是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都得到通知并被自动更新。观察者模式也叫发布-订阅模式(Publish-Subscribe)

一、观察者模式的基本介绍

1.1 意图

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都得到通知并被自动更新。

1.2 结构

观察者模式基本的结构如下图所示:

主要包括如下几个部分:

  • Subject(目标)
    • 目标知道它的观察者,可以有任意多个观察者观察同一个目标
    • 提供注册和删除观察者对象的接口
  • Observer(观察者)
    • 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
  • ConcreteObserver(具体观察者)
    • 实现Observer的更新接口以使自身状态与目标的状态保持一致。
代码语言:javascript
复制
JDK提供了java.util.Observer和java.util.Observable可以实现观察者模式。
  • java.util.Observable

从上述Observable的截图可以看出,Observerable维护一个changed状态需要通知的订阅者列表

代码语言:javascript
复制
    private boolean changed = false;
    private Vector<Observer> obs;

当状态改变的时候,会依次通知各个订阅者

代码语言:javascript
复制
    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);
    }

另外,还有添加订阅者、删除订阅者等方法。

  • java.util.Observer
代码语言:javascript
复制
public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an {@code Observable} object's
     * {@code notifyObservers} 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}
     *                 method.
     */
    void update(Observable o, Object arg);
}

Observer接口就一个update方法,用于获取来自主题的消息更新。

二、使用JDK内置的Observer完成一个观察者模式示例

一个项目完成了,大家一起去聚餐嗨皮。看着时间还早,Eric提议说要不我们再去唱会歌吧。大家都可以开心说“好啊”。Eric说我先去KTV看下,具体房间号定好,我再通知大家。

就这样一个场景,很适合观察者模式,借助JDK内置的Observer和Observable,我们来看下如何完成。

  • KtvOrder - 主题(发布者)
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.observer;

import java.util.Observable;

public class KtvOrder extends Observable {

  private String name;

  public KtvOrder(String name) {
    this.name = name;
  }
  
  public void sendMessage(String message) {
    System.out.println(String.format("[%s]发送通知: %s", name,message));
    this.setChanged();
    this.notifyObservers(message);
  }

  /**
   * @return the name
   */
  public String getName() {
    return name;
  }

  @Override
  public String toString() {
    return "KtvOrder [name=" + name + "]";
  }
  
}
  • KtvParticipant - 被观察者(订阅者)
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.observer;

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

public class KtvParticipant implements Observer {

  private String name;
  
  public KtvParticipant(String name) {
    this.name = name;
  }

  public void update(Observable o, Object arg) {
    KtvOrder order = null;
    if(o instanceof KtvOrder) {
      order = (KtvOrder)o;
      System.out.println(String.format("[%s]收到来自[%s]的通知信息==> %s", name,order.getName(),arg.toString()));
    }
  }

}
  • 测试case
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.observer;

public class ObserverMain {

  public static void main(String[] args) {
    KtvOrder order = new KtvOrder("Eric");
    
    KtvParticipant john = new KtvParticipant("John");
    KtvParticipant lucy = new KtvParticipant("Lucy");
    KtvParticipant lily = new KtvParticipant("Lily");
    
    order.addObserver(john);
    order.addObserver(lucy);
    order.addObserver(lily);
    
    order.sendMessage("西城广场银乐迪506");
  }
}

输出结果:

代码语言:javascript
复制
[Eric]发送通知: 西城广场银乐迪506
[Lily]收到来自[Eric]的通知信息==> 西城广场银乐迪506
[Lucy]收到来自[Eric]的通知信息==> 西城广场银乐迪506
[John]收到来自[Eric]的通知信息==> 西城广场银乐迪506

小结

本文对观察者模式进行了简单介绍,并使用JDK提供的java.util.Observer和java.util.Observable完成一个示例。

ps: java.util.Observer和java.util.Observable从JDK9开始,已经标注为过时。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档