`
java-mans
  • 浏览: 11388009 次
文章分类
社区版块
存档分类
最新评论

Java中的观察者模式 —— Observable和Observer

 
阅读更多

一、观察者模式介绍

在Java中通过Observable类和Observer接口实现了观察者模式。一个Observer对象监视着一个Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。

如果画面A是显示数据库里面的数据,而画面B修改了数据库里面的数据,那么这时候画面A就要重新Load。这时候就可以用到观察者模式

二、观察者模式实现方法

java.util.Observable中有两个方法对Observer特别重要

①setChanged()方法

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

    /**
     * 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);
            }
        }
    }

以上两个方法十分重要

setChanged()方法 ——

用来设置一个内部标志位注明数据发生了变化

notifyObservers()方法 / notifyObservers(Object data)方法 ——

通知所有的Observer数据发生了变化,这时所有的Observer会自动调用复写好的update(Observable observable, Object data)方法来做一些处理(比如说画面数据的更新)。

我们可以看到通知Observer有两个方法,一个无参,一个有参。那么这个参数有什么作用呢?

其中一个作用:现在我不想通知所有的Observer,而只想其中一个指定的Observer做一些处理,那么就可以传一个参数作为ID,然后在所有的Observer中判断,每个Observer判断只有接收到底参数ID是属于自己的才做一些处理。

当然参数还有其他作用,我只是举了个例子。


下面举个例子加以说明:

import java.util.Observable;  
/**
 * 被观察者类
 */    
public class SimpleObservable extends Observable  
{  
   private int data = 0;  
    
   public int getData(){   
       return data;  
   }  
    
   public void setData(int i){  
       if(this.data != i) { 
          this.data = i; 
          setChanged();  

          //只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。
          notifyObservers();    
       }  
   }  
}  

上面这个类是一个被观察者类,它继承了Observable类,表示这个类是可以被观察的。

然后在setData()方法里面,也就是数据改变的地方,来调用Observable类的setChanged()方法和notifyObservers()方法,表示数据已改变并通知所有的Observer调用它们的update()方法做一些处理。

注意:只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。


/**
 * 观察者类
 */      
public class SimpleObserver implements Observer  
{  
   public SimpleObserver(SimpleObservable simpleObservable){  
      simpleObservable.addObserver(this );  
   }  
    
   public void update(Observable observable ,Object data){  // data为任意对象,用于传递参数
      System.out.println(“Data has changed to” + (SimpleObservable)observable.getData());  
   }  
} 


通过生成被观察者(SimpleObservable类)的实例,来调用addObserver(this)方法让观察者(SimpleObserver类)达到观察被观察者(SimpleObservable类)的目的。

然后还要复写update()方法,做数据改变后的一些处理。

下面可以写一个简单的测试类来测试一下

public class SimpleTest  
{  
   public static void main(String[] args){  
      SimpleObservable doc = new SimpleObservable ();  
      SimpleObserver view = new SimpleObserver (doc);  
      doc.setData(1);  
      doc.setData(2);  
      doc.setData(2);  
      doc.setData(3);   
   }  
} 

运行结果如下

Data has changed to 1 
Data has changed to 2  //第二次setData(2)时由于没有setChange,所以update没被调用
Data has changed to 3

下面介绍一个Observable类的其他一些属性和方法

属性 ——

// observers是一个List,保存着所有要通知的observer。    
List<Observer> observers = new ArrayList<Observer>();
// changed是一个boolean型标志位,标志着数据是否改变了。
boolean changed = false;

方法 ——

// 添加一个Observer到列表observers中
public void addObserver(Observer observer) {
    if (observer == null) {
        throw new NullPointerException();
    }
    synchronized (this) {
        if (!observers.contains(observer))
            observers.add(observer);
    }
}

// 从列表observers中删除一个observer

public synchronized void deleteObserver(Observer observer) {
    observers.remove(observer);
}

// 清空列表observers
public synchronized void deleteObservers() {
    observers.clear();
}

// 返回列表observers中observer的个数

public int countObservers() {
    return observers.size();
}


// 重置数据改变标志位为未改变
protected void clearChanged() { 
changed = false;
}

// 将数据改变标志位设置为改变

protected void setChanged() { 
    changed = true;
}


// 判断标志位的值
public boolean hasChanged() { 
    return changed;
}

// 通知所有observer(无参)
public void notifyObservers() {
    notifyObservers(null);
}
// 通知所有observer(有参)
@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); 
        } 
    }
}


注意:在Observer对象销毁前一定要用deleteObserver将其从列表中删除,也就是在onDestroy()方法中调用deleteObserver()方法。

不然因为还存在对象引用的关系,Observer对象不会被垃圾收集,造成内存泄漏,并且已死的Observer仍会被通知到,有可能造成意料外的错误,而且随着列表越来越大,notifyObservers操作也会越来越慢。


下面2个工程是Observable与Observer的经典运用,是android实现的单指拖动放大图片的操作

两个例子:

http://download.csdn.net/detail/tianjf0514/4237628

http://download.csdn.net/download/tianjf0514/4237634



分享到:
评论

相关推荐

    java实现观察者模式-Java内置的观察者模式(基于Observable和Observer)

    Java内置的Observable类和Observer接口提供了基本的观察者模式功能,你可以通过继承Observable类和实现Observer接口来使用

    Java观察者设计模式(Observable和Observer)

    主要介绍了 Java观察者设计模式(Observable和Observer)的相关资料,需要的朋友可以参考下

    observable-observer

    观察者模式介绍:Observable和Observer原理分析,手动实现简单MyObservable和MyObserver

    观察者模式相关

    这样一来 当一个对象改变状态时 依赖它的对象都会收到通知并自动跟新 Java已经提供了对观察者Observer模式的默认实现 Java对观察者模式的支持主要体现在Observable类和Observer接口 "&gt;观察者 Observer 模式定义:在...

    java观察者模式介绍

    Observer模式定义对象间的一对多的依赖关系,当一个对象(被观察者)的状态发生改变...从名字上可以清楚的看出两者在Observer 设计模式中分别扮演的角色:Observer是观察者角色,Observable是被观察目标(subject)角色。

    java观察者模式demo----未使用java工具类

    观察者设计模式,java语言实现,完全自己代码实现,未使用observable和observer

    观察者模式类文件

    观察者模式主要有观察者和被观察者2个对象,在该模式中,Observable表示被观察者,这个对象是一个抽象类,只能被继承。 Observer表示观察者,他是一个接口,所以观察者可以有多个,实现了该接口的类都是属于观察者。

    观察者模式示例代码 android studio kotlin代码 基于java.uitl.*

    android 观察者模式示例代码 android studio kotlin代码 基于java.uitl.*

    我理解的 js 的观察者模式 Observable

    NULL 博文链接:https://jiangxiao-2000.iteye.com/blog/1893601

    MVC小例子 使用Java类库observer和Observable

    这是最简单的一个MVC实例,通过它你可以了解MVC的基本工作原理。

    C++实现观察者模式

    要通知到需要了解该变化的类,Windows编程中经常用到的是发消息,要是没有Windows的消息机制的话,自己做一套消息机制倒是可以,但也是徒增了工作量,再次想到了设计模式中的观察者模式,也可以实现这个想法,具体...

    Observable与Observer

    NULL 博文链接:https://best-sheng.iteye.com/blog/1024369

    Java实现MVC球体

    Java实现一个模型、两个视图和两个控制器的功能软件,即采用MVC模式或者说是观察者模式,本程序通过输入球体半径,显示球体形状,面积体积等 Sphere.java package Model; import java.util.Observable; public class...

    Python程序中的观察者模式结构编写示例

    观察者模式提供了一种对象设计,让主题和观察者之间松耦合。 设计原则 为了交互对象之间的松耦合设计而努力。松耦合的设计之所以能让我们建立有弹性的系统,能够应对变化,是因为对象之间的互相依赖降到了最低。 ...

    Android设计模式之观察者模式源码

    观察者模式(Observer Pattern) - 定义对象间的一种一个(Observable)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。

    EventBus消息总线

    EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。 ...

    Android观察者模式简单实现Demo

    Android观察者模式简单实现Demo,同步博文http://blog.csdn.net/qq_28690547/article/details/50661603

    RxJava 操作符使用

    三要素Rxjava原理 基于 一种扩展的观察者模式的响应式编程框架RxJava原理可总结为:被观察者 (Observable) 通过 订阅(Subscribe) 按顺序发送事件 给观察者 (Observer), 观察者(Observer) 按顺序接收事件 & ...

    Head.First.设计模式.中文版 1-8章

     使用Java内建的观察者模式   java.util.Observable的黑暗面  设计箱内的工具  习题解答 …… 3 装饰者模式:装饰对象 4 工厂模式:烘烤OO的精华 5 单件模式:独一无二的对象 6 命令模式:封装调用 7 ...

    zen-observable:Java的Observables的实现

    禅宗可观察 Observables for JavaScript的实现。 需要Promise或Promise polyfill。 安装 npm install zen-observable 用法 import Observable from 'zen-observable' ; Observable . of ( 1 , 2 , 3 ) . subscribe ...

Global site tag (gtag.js) - Google Analytics