您的位置:首页 > 编程语言 > Java开发

Java_观察者模式(Observable和Observer)

2017-08-16 16:45 555 查看

、观察者模式介绍

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

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

二、观察者模式实现方法

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

①setChanged()方法

[java] view
plain copy

/** 

 * 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)方法

[java] view
plain copy

/** 

 * 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是属于自己的才做一些处理。

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

下面举个例子加以说明:

[java] view
plain copy

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(),否则什么都不干。

[java] view
plain copy

/** 

 * 观察者类 

 */        

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()方法,做数据改变后的一些处理。

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

[java] view
plain copy

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);     

   }    

}   

运行结果如下

[plain] view
plain copy

Data has changed to 1   

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

Data has changed to 3  

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

属性 ——

[java] view
plain copy

// observers是一个List,保存着所有要通知的observer。      

List<Observer> observers = new ArrayList<Observer>();  

// changed是一个boolean型标志位,标志着数据是否改变了。  

boolean changed = false;  

方法 ——

[java] view
plain copy

// 添加一个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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: