Java观察者模式 java.util.Observable 与 java.util.Observer 的理解

Part I


JDK1.2后,Java提供了对观察者模式的支持接口和实现类。


其中接口 java.util.Observer 用来指定观察者,观察者必须实现 void update(Observable o, Object arg) 方法。


而 java.util.Observable 用来指定观察物(被观察者、可被观察的),并且提供了一系列的方法。读者可以很轻易的使用这个接口和实现类来实现观察者模式。


Part II



java.util.Observer 只有一个简单的方法 void update(Observable o, Object arg)


其中,参数 Observable o 用于指定触发 update 方法的对象, Object arg 用于指定触发 update 方法时候的附加参数。


如果有桌面应用开发的读者应该很了解,这跟事件处理机制是完全一样的,其中 Observable o 可被看作事件源。 Object arg 可被看作消息。


 

Part III


说了那么多,我们还是动手写个例子吧。这里我们以读者订阅杂志为例子。


package com.gzmu.observer.observable;


import java.util.Observable;


public class Publisher extends Observable {
    
    private String magazineName;
    


    public String getMagazineName() {
        return magazineName;
    }
    
    public void publish(String magazineName) {
        this.magazineName = magazineName;
        setChanged();
        notifyObservers(this);
    }
    
}



package com.gzmu.observer.observer;


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


import com.gzmu.observer.observable.Publisher;


public class Reader implements Observer {


    @Override
    public void update(Observable o, Object arg) {
        Publisher p = (Publisher) o;
        System.out.println("我要订阅" + p.getMagazineName());
    }


}



package com.gzmu.observer.test;




import org.junit.Test;


import com.gzmu.observer.observable.Publisher;


public class TestCase {


    @Test
    public void register() {


        Publisher publisher = new Publisher();
        publisher.publish("Kent.Kuan的技术空间");


    }


}



这里很清楚的看到,当出版社出版杂志的时候,会主动的告知读者,读者就会订阅杂志,这也是一种主动推送的模式。


Part IV


这里大家会发现,调用 notifyObservers() 的时候,为什么传进当前对象 this 呢?而这个 this, 我们在读者那也没用到啊。这个问题曾经也让我觉得很苦恼,之前我也不清楚为什么观察者要拿到被观察对象的引用,但是,我们看看下面这个例子。


首先我们引用一个新的类:


package com.gzmu.observer.observable;


import java.util.Observable;


public class TVStation extends Observable {


    private String programmeName;


    public void play(String programmeName) {
        this.programmeName = programmeName;
        setChanged();
        notifyObservers(this);
    }


    public String getProgrammeName() {
        return programmeName;
    }


}



然后修改Reader和TestCase:


package com.gzmu.observer.observer;


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


import com.gzmu.observer.observable.Publisher;
import com.gzmu.observer.observable.TVStation;


public class Reader implements Observer {


    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof Publisher) {
            Publisher p = (Publisher) o;
            System.out.println("我要订阅" + p.getMagazineName());
        }
        if (o instanceof TVStation) {
            TVStation t = (TVStation) o;
            System.out.println("我要收看" + t.getProgrammeName());
        }
    }


}



package com.gzmu.observer.test;


import org.junit.Test;


import com.gzmu.observer.observable.Publisher;
import com.gzmu.observer.observable.TVStation;
import com.gzmu.observer.observer.Reader;


public class TestCase {
    
    @Test
    public void register() {
        
        Reader reader = new Reader();
        
        Publisher publisher = new Publisher();
        publisher.addObserver(reader);
        
        TVStation tvStation = new TVStation();
        tvStation.addObserver(reader);
        
        publisher.publish("Kent.Kwan的技术空间");
        tvStation.play("色戒");
        
    }
    
}



最后我们可以看到,同一个观察者其实是可以注册到不同的被观察者上面的,而传过来的 Oberverable o 其实可以用来检验到底是谁发过来的消息。


除此以外,我们还可以在接受到消息之后,进行撤销观察的工作。


package com.gzmu.observer.observer;


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


import com.gzmu.observer.observable.Publisher;
import com.gzmu.observer.observable.TVStation;


public class Reader implements Observer {


    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof Publisher) {
            Publisher p = (Publisher) o;
            p.deleteObserver(this);
            System.out.println("我要订阅" + p.getMagazineName());
        }
        if (o instanceof TVStation) {
            TVStation t = (TVStation) o;
            System.out.println("我要收看" + t.getProgrammeName());
        }
    }


}



 


通过 deleteObserver() 方法就可以撤销观察出版社对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值