zoukankan      html  css  js  c++  java
  • 利用Java提供的Observer接口和Observable类实现观察者模式

    对于观察者模式,其实Java已经为我们提供了已有的接口和类。对于订阅者(Subscribe,观察者)Java为我们提供了一个接口,JDK源码如下:

    1 package java.util;
    2 
    3 public interface Observer {
    4     void update(Observable o, Object arg);
    5 }

    和我们上一篇实现的观察者一样,仅提供一个update方法用于接收通知者的通知做出相应改变。

    我们再来看看Java为我们提供了一个怎样的通知者(Publish,发布者),JDK源码如下:

     1 package java.util;
     2 
     3 public class Observable {
     4     private boolean changed = false;  //是否改变状态
     5     private Vector obs;    //Vector利用同步方法来线程安全,线程安全在多线程情况下不会造成数据混乱
     6 
     7     public Observable() {
     8         obs = new Vector();
     9     }
    10 
    11     public synchronized void addObserver(Observer o) {
    12         if (o == null)
    13             throw new NullPointerException();
    14         if (!obs.contains(o)) {
    15             obs.addElement(o);
    16         }
    17     }
    18 
    19     public synchronized void deleteObserver(Observer o) {
    20         obs.removeElement(o);
    21     }
    22 
    23     public void notifyObservers() {
    24         notifyObservers(null);
    25     }
    26 
    27     public void notifyObservers(Object arg) {
    28         Object[] arrLocal;
    29 
    30         synchronized (this) {
    31             if (!changed)    //状态值未改变时返回,不通知
    32                 return;
    33             arrLocal = obs.toArray();  //将Vector转换成数组
    34             clearChanged();    //重置状态
    35         }
    36 
    37         for (int i = arrLocal.length-1; i>=0; i--)
    38             ((Observer)arrLocal[i]).update(this, arg);
    39     }
    40 
    41     public synchronized void deleteObservers() {
    42         obs.removeAllElements();
    43     }
    44 
    45     protected synchronized void setChanged() {
    46         changed = true;
    47     }
    48 
    49     protected synchronized void clearChanged() {
    50         changed = false;
    51     }
    52 
    53     public synchronized boolean hasChanged() {
    54         return changed;
    55     }
    56 
    57     public synchronized int countObservers() {
    58         return obs.size();
    59     }
    60 }

    不得不说,Java源码考虑得就是比自己写的要好。首先,使用Vector,Vector相比于ArrayList来说,它是线程安全的。其次,在添加和删除观察者时对两个方法使用了synchronized关键字,这都是在为多线程考虑。确实Java源码并不是那么可怕,它同样也是由一些最简单最基础的组合而来。

    接下来我们来看看是如何利用Java提供的接口和方法来实现观察者模式。

     1 package day_10_observer_jdk;
     2 
     3 import java.util.Observable;
     4 import java.util.Observer;
     5 
     6 /**
     7  * 实现java.util.Observer接口的观察者
     8  * @author turbo
     9  *
    10  * 2016年9月14日
    11  */
    12 public class Subscribe implements Observer {
    13 
    14     public Subscribe(Observable o){
    15         o.addObserver(this);        //将该观察者放入待通知观察者里
    16     }
    17     /* (non-Javadoc)
    18      * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
    19      */
    20     @Override
    21     public void update(Observable o, Object arg) {
    22         System.out.println("收到通知:" + ((Publish)o).getData());
    23     }
    24 
    25 }
     1 package day_10_observer_jdk;
     2 
     3 import java.util.Observable;
     4 
     5 /**
     6  * 继承java.util.Observable的通知者
     7  * @author turbo
     8  *
     9  * 2016年9月14日
    10  */
    11 public class Publish extends Observable {
    12     private String data = "";
    13 
    14     public String getData() {
    15         return data;
    16     }
    17 
    18     public void setData(String data) {
    19         if (!this.data.equals(data)){
    20             this.data = data;
    21             setChanged();    //改变通知者的状态
    22         }
    23         notifyObservers();    //调用父类Observable方法,通知所有观察者
    24     }
    25 }

    客户端测试代码:

     1 package day_10_observer_jdk;
     2 
     3 /**
     4  * @author turbo
     5  *
     6  * 2016年9月14日
     7  */
     8 public class Main {
     9 
    10     /**
    11      * @param args
    12      */
    13     public static void main(String[] args) {
    14         Publish publish = new Publish();
    15         Subscribe subscribe = new Subscribe(publish);
    16         
    17         publish.setData("开始");
    18     }
    19 
    20 }

    这样我们就利用了Java给我们提供的Observer接口和Observable类实现了观察者模式。上一篇我们提到了事件委托,我们在下一篇来了解一下什么是事件委托。

  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/5874015.html
Copyright © 2011-2022 走看看