Observer与Observable

在Java中通过 Observable 类和 Observer 接口实现了观察者模式。一个 Observer 对象监视着一个 Observable 对象的变化,当 Observable 对象发生变化时, Observer 得到通知,就可以进行相应的工作。例如在文档/视图结构中,文档被修改了,视图就会得到通知。
java.util.Observable 中有两个方法对Observer特别重要,一个是 setChange() 方法用来设置一个内部标志位注明数据发生了变化;一个是 notifyObservers() 方法会去调用一个列表中所有的Observer的update()方法,通知它们数据发生了变化。
Observer 通过 Observable addObserver() 方法把自己添加到这个列表中。这个列表虽然由 Observable 拥有,但 Observable 并不知道到底有哪些 Observer 正在观察等待通知。 Observable 只提供一个方法让 Observer 能把自己添加进列表,并保证会去通知 Observer 发生了变化。通过这种机制,可以有任意多个 Observer Observable 进行观察,而不影响 Observable 的实现。当然一个 Observer 也可以观察多个 Observable
Observer Observable 的简单使用可以参照 实例1 SimpleObservable.java文件 SimpleObserver.java文件.
Observable 类有两个私有变量。一个boolean型的标志位,setChange()将它设为真,只有它为真时,notifyObservers方法才会调用 Observer update 方法,clearChange()设标志位为假,hasChange返回当前标志位的值。另一个是一个Vector,保存着一个所有要通知的 Observer 列表,我们可以使用 addObserver 方法添加Observer到列表, deleteObserver 从列表中删除指定 Observer deleteObservers 清空列表,使用 countObservers 方法返回列表中Observer的数目,在 Observer 对象销毁前一定要用 deleteObserver 将其从列表中删除,不然因为还存在对象引用的关系,Observer对象不会被垃圾收集,造成内存泄漏,并且已死的Observer仍会被通知到,有可能造成意料外的错误,而且随着列表越来越大,notifyObservers操作也会越来越慢。
Observable 的所有方法都是同步的,保证了在一个线程对其标志位、列表进行操作时,不会有其它线程也在操作它。
Observable 的notifyObservers(Object obj)形式可以再调用update时将参数传进去。
Observer 接收到通知的顺序是 越晚加入列表的越先通知 Observer 的update方法会被依次调用,由于 Observable notifyObservers 方法 Observer update 方法其实是在同一个线程中被调用而且调用 一个 update 方法返回后才进行下一个 update 方法的调用,这样当 update 中有大量操作时,最好将其中的工作给另一个线程来做,具体可以参照 实例1 SimpleObserver2.java 文件
实例1
SimpleObservable.java文件

  

package com . lenovo . robin ;
import java . util . Observable ;
public class SimpleObservable extends Observable
{
private int data = 0 ;
private String name ;
public SimpleObservable ( String name )
{
this . name = name ;
}
public String getName ()
{
return name ;
}
public int getData ()
{
return data ;
}
public void setData ( int i )
{
if ( this . data != i )
{
this . data = i ;
/* 只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。 */
setChanged ();
notifyObservers ();
}
}
}

SimpleObserver.java文件

  

package com . lenovo . robin ;
import java . util . Observable ;
import java . util . Observer ;
public class SimpleObserver implements Observer
{
private String name ;
public SimpleObserver ( String name ){
this . name = name ;
}
public void update ( Observable o , Object arg ){
SimpleObservable observable =( SimpleObservable ) o ;
System . out . println ( name + " found that Data of " + observable . getName ()+ " has changed to " + observable . getData ());
}
}

SimpleObserver2.java

  

package com . lenovo . robin ;
import java . util . Observable ;
import java . util . Observer ;
import java . util . concurrent . ArrayBlockingQueue ;
public class SimpleObserver2 implements Observer , Runnable
{
private String name ;
public SimpleObserver2 ( String name ){
this . name = name ;
}
/* 利用一个消息队列来接收Observable的通知,保证消息不会丢失 */
ArrayBlockingQueue < Message > queue = new ArrayBlockingQueue < Message >( 100 );
Thread thread = null ;
public void run ()
{
while ( true )
{
Message msg ;
try
{
msg = queue . take ();
Observable o = msg . observable ;
Object obj = msg . object ;
SimpleObservable observable =( SimpleObservable ) o ;
System . out . println ( name + " found that Data of " + observable . getName ()+ " has changed to " + observable . getData ());
// …执行相应的工作
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void update ( Observable o , Object arg )
{
Message msg = new Message ( o , arg );
try
{
queue . put ( msg );
} catch ( InterruptedException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if(thread==null){
thread=new Thread(this);
thread.start();
}
}
class Message
{
Observable observable ;
Object object ;
Message ( Observable o , Object arg )
{
this . observable = o ;
this . object = arg ;
}
}
}

使用的代码片段

  

SimpleObservable observable01 = new SimpleObservable ( "SimpleObservable01" );
SimpleObservable observable02 = new SimpleObservable ( "SimpleObservable02" );
SimpleObserver observer1_0 = new SimpleObserver ( "SimpleObserver1-0" );
SimpleObserver observer1_1 = new SimpleObserver ( "SimpleObserver1-1" );
SimpleObserver2 observer2_0 = new SimpleObserver2 ( "SimpleObserver2-0" );
observable01 . addObserver ( observer1_0 );
observable01 . addObserver ( observer1_1 );
observable01 . addObserver ( observer2_0 );
observable02 . addObserver ( observer1_0 );
observable02 . addObserver ( observer1_1 );
observable02 . addObserver ( observer2_0 );
observable01 . setData ( 1 );
observable01 . setData ( 2 );
observable01 . setData ( 2 );
observable01 . setData ( 3 );
observable02 . setData ( 100 );
observable02 . setData ( 110 );

运行结果

  

SimpleObserver1 - 1 found that Data of SimpleObservable01 has changed to 1
SimpleObserver1 - 0 found that Data of SimpleObservable01 has changed to 1
SimpleObserver1 - 1 found that Data of SimpleObservable01 has changed to 2
SimpleObserver1 - 0 found that Data of SimpleObservable01 has changed to 2
SimpleObserver1 - 1 found that Data of SimpleObservable01 has changed to 3
SimpleObserver1 - 0 found that Data of SimpleObservable01 has changed to 3
SimpleObserver1 - 1 found that Data of SimpleObservable02 has changed to 100
SimpleObserver1 - 0 found that Data of SimpleObservable02 has changed to 100
SimpleObserver2 - 0 found that Data of SimpleObservable01 has changed to 3
SimpleObserver2 - 0 found that Data of SimpleObservable01 has changed to 3
SimpleObserver2 - 0 found that Data of SimpleObservable01 has changed to 3
SimpleObserver2 - 0 found that Data of SimpleObservable02 has changed to 110
SimpleObserver2 - 0 found that Data of SimpleObservable02 has changed to 110
SimpleObserver1 - 1 found that Data of SimpleObservable02 has changed to 110
SimpleObserver1 - 0 found that Data of SimpleObservable02 has changed to 110

Observable.java源码

  

/*
* @(#)Observable.java 1.39 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java . util ;
/**
* This class represents an observable object, or "data"
* in the model-view paradigm. It can be subclassed to represent an
* object that the application wants to have observed.
* <p>
* An observable object can have one or more observers. An observer
* may be any object that implements interface <tt>Observer</tt>. After an
* observable instance changes, an application calling the
* <code>Observable</code>'s <code>notifyObservers</code> method
* causes all of its observers to be notified of the change by a call
* to their <code>update</code> method.
* <p>
* The order in which notifications will be delivered is unspecified.
* The default implementation provided in the Observable class will
* notify Observers in the order in which they registered interest, but
* subclasses may change this order, use no guaranteed order, deliver
* notifications on separate threads, or may guarantee that their
* subclass follows this order, as they choose.
* <p>
* Note that this notification mechanism is has nothing to do with threads
* and is completely separate from the <tt>wait</tt> and <tt>notify</tt>
* mechanism of class <tt>Object</tt>.
* <p>
* When an observable object is newly created, its set of observers is
* empty. Two observers are considered the same if and only if the
* <tt>equals</tt> method returns true for them.
*
* @author Chris Warth
* @version 1.39, 11/17/05
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
* @see java.util.Observer
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
* @since JDK1.0
*/
public class Observable {
private boolean changed = false ;
private Vector obs ;
/** Construct an Observable with zero Observers. */
public Observable () {
obs = new Vector ();
}
/**
* Adds an observer to the set of observers for this object, provided
* that it is not the same as some observer already in the set.
* The order in which notifications will be delivered to multiple
* observers is not specified. See the class comment.
*
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
public synchronized void addObserver ( Observer o ) {
if ( o == null )
throw new NullPointerException ();
if (! obs . contains ( o )) {
obs . addElement ( o );
}
}
/**
* Deletes an observer from the set of observers of this object.
* Passing <CODE>null</CODE> to this method will have no effect.
* @param o the observer to be deleted.
*/
public synchronized void deleteObserver ( Observer o ) {
obs . removeElement ( o );
}
/**
* If this object has changed, as indicated by the
* <code>hasChanged</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to
* indicate that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and <code>null</code>. In other
* words, this method is equivalent to:
* <blockquote><tt>
* notifyObservers(null)</tt></blockquote>
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers () {
notifyObservers ( null );
}
/**
* If this object has changed, as indicated by the
* <code>hasChanged</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to indicate
* that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and the <code>arg</code> argument.
*
* @param arg any object.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
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 );
}
/**
* Clears the observer list so that this object no longer has any observers.
*/
public synchronized void deleteObservers () {
obs . removeAllElements ();
}
/**
* Marks this <tt>Observable</tt> object as having been changed; the
* <tt>hasChanged</tt> method will now return <tt>true</tt>.
*/
protected synchronized void setChanged () {
changed = true ;
}
/**
* Indicates that this object has no longer changed, or that it has
* already notified all of its observers of its most recent change,
* so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
* This method is called automatically by the
* <code>notifyObservers</code> methods.
*
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
*/
protected synchronized void clearChanged () {
changed = false ;
}
/**
* Tests if this object has changed.
*
* @return <code>true</code> if and only if the <code>setChanged</code>
* method has been called more recently than the
* <code>clearChanged</code> method on this object;
* <code>false</code> otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged () {
return changed ;
}
/**
* Returns the number of observers of this <tt>Observable</tt> object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers () {
return obs . size ();
}
}

Observer.java源码

  

/*
* @(#)Observer.java 1.20 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java . util ;
/**
* A class can implement the <code>Observer</code> interface when it
* wants to be informed of changes in observable objects.
*
* @author Chris Warth
* @version 1.20, 11/17/05
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> 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</code>
* method.
*/
void update ( Observable o , Object arg );
}

结束!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值