Java设计模式2:观察者模式2(使用java内置的观察者)

来源:互联网 发布:centos配置rsyslog 编辑:程序博客网 时间:2024/05/29 14:19

一.使用java内置的观察者
1.介绍:
在java.util包中包含有基本的Observer接口和Observable抽象类.功能上和Subject接口和Observer接口类似.不过在使用上,就方便多了,因为许多功能比如说注册,删除,通知观察者的那些功能已经内置好了.

2.如何使对象变为观察者:
实现观察者接口(java.util.Observer),然后调用Observable对象的addObserver()方法.不想再当观察者时,调用deleteObserver()就可以了

3.被观察者(主题)如何发出通知:
第一步:先调用setChanged()方法,标识状态已经改变的事实.

第二步:调用notifyObservers()方法或者notifyObservers(Object arg),这就牵扯到推(push)和拉(pull)的方式传送数据.如果想用push的方式”推”数据给观察者,可以把数据当做数据对象传送给notifyObservers(Object arg)方法,其中的arg可以为任意对象,意思是你可以将任意对象传送给每一个观察者.如果调用不带参数的notifyObserver()方法,则意味着你要使用pull的方式去主题对象中”拉”来所需要的数据.

4.观察者如何接收通知
观察者只需要实现一个update(Observable o,Object arg)方法,第一个参数o,是指定通知是由哪个主题下达的,第二个参数arg就是上面notifyObserver(Object arg)里传入的数据,如果不传该值,arg为null

二.使用java内置观察者修改气象站案例
1.class WeatherData.java(气象站 主题(继承了java.util.Observable))

package tiglle.pattern.Observer.javaObserver;import java.util.Observable;//气象站 主题(继承了java.util.Observable)public class WeatherData extends Observable{    //天气数据    private int wendu;//温度    private int shidu;//湿度    private int qiya;//气压    //天气数据发生改变时调用,通知观察者    public void weatherChanged(){        //设置父类的changed属性为true,为true时,观察者参会真正更新数据。此方法在更新观察者时拥有更多的弹性        setChanged();        //通知观察者(调用注册进来的观察者的update方法)        notifyObservers();//采用pull拉的方法,观察者自己调用主题的getter方法获取数据//      ;//采用push推的方法,观察者从update方法中的第二个参数args中获取主题传入的数据    }    //设置天气数据,并通知观察者    public void setParam(int wendu,int shidu,int qiya){        this.wendu = wendu;        this.shidu = shidu;        this.qiya = qiya;        //通知观察者        weatherChanged();    }    //设置getter方法,以便观察者自己拉pull数据    public int getWendu() {        return wendu;    }    public int getShidu() {        return shidu;    }    public int getQiya() {        return qiya;    }}

2.interface Report.java(报导接口,其他功能)

package tiglle.pattern.Observer.javaObserver;//报导接口public interface Report {    public void report(int wendu,int shidu,int qiya);}

3.class HuBeiTv.java(湖北电视台 观察者1(实现java.util.Observer接口))

package tiglle.pattern.Observer.javaObserver;import java.util.Observable;import java.util.Observer;//湖北电视台  观察者1(实现java.util.Observer接口)public class HuBeiTv implements Observer,Report{    //主题,以便在观察者的构造方法中注册进主题    private Observable observable;    //构造函数,实例化时注册进指定的主题中    public HuBeiTv(Observable observable) {        this.observable = observable;        observable.addObserver(this);    }    @Override    public void update(Observable o, Object arg) {        //使用pull拉的方式让观察者自己用getter从主题获取数据        WeatherData weatherData = (WeatherData) o;        report(weatherData.getWendu(), weatherData.getShidu(), weatherData.getQiya());    }    @Override    public void report(int wendu,int shidu,int qiya) {        System.out.println("湖北人民请注意,当前天气数据,温度:"+wendu+",湿度:"+shidu+",气压:"+qiya);    }}

4.class HuNanTv.java(湖南电视台 观察者2(实现java.util.Observer接口))

package tiglle.pattern.Observer.javaObserver;import java.util.Observable;import java.util.Observer;//湖南电视台  观察者2(实现java.util.Observer接口)public class HuNanTv implements Observer,Report{    //主题,以便在观察者的构造方法中注册进主题    private Observable observable;    public HuNanTv(Observable observable) {        this.observable = observable;        observable.addObserver(this);    }    @Override    public void update(Observable o, Object arg) {        //使用pull拉的方式让观察者自己用getter从主题获取数据        WeatherData weatherData = (WeatherData) o;        report(weatherData.getWendu(), weatherData.getShidu(), weatherData.getQiya());        //使用push推的方式获取主题的数据,主题需要调用有参数的notifyObservers(Object o)方法,并传入数据//      int[] param = (int[]) arg;//      report(param[0], param[1], param[2]);    }    @Override    public void report(int wendu, int shidu, int qiya) {        System.out.println("湖南人民请注意,当前天气数据,温度:"+wendu+",湿度:"+shidu+",气压:"+qiya);    }}

5.MainExec.java(Client(测试main方法))

package tiglle.pattern.Observer.javaObserver;public class MainExec {    public static void main(String[] args) {        //实例主题        WeatherData weatherData = new WeatherData();        //实例观察者        HuBeiTv huBeiTv = new HuBeiTv(weatherData);        HuNanTv huNanTv = new HuNanTv(weatherData);        //主题数据发生改变        weatherData.setParam(30, 20, 10);        weatherData.setParam(10, 20, 30);    }}运行结果:湖南人民请注意,当前天气数据,温度:30,湿度:20,气压:10湖北人民请注意,当前天气数据,温度:30,湿度:20,气压:10湖南人民请注意,当前天气数据,温度:10,湿度:20,气压:30湖北人民请注意,当前天气数据,温度:10,湿度:20,气压:30
原创粉丝点击