设计模式详解之————观察者模式(二)

引言

从我的上篇博客中,我们可以针对气象预报的例子思考两个问题:
(1)观察者种类这么多,每个观察者关心的数据不同,但是被强制通知了一堆数据,这种设计是不是冗余了?
(2)如果哪一天观察者需要拓展功能,需要增加更多的状态,岂不是需要修改和更新每个观察者的调用?

这个问题的解决方案也简单,我们暂且不论,先来看看JAVA内置的观察者模式是怎么实现的。

Java内置的观察者模式

首先我们来看一下JDK的源码。

package java.util;
public class Observable {
    private boolean changed = false;//标记被观察者是否改变
    private Vector<Observer> obs;//使用线程安全的Vector存储观察者对象
    public Observable() {
        obs = new Vector<>();
    }
    public synchronized void addObserver(Observer o) {//观察者注册
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
    public synchronized void deleteObserver(Observer o) {//观察者删除
        obs.removeElement(o);
    }
    public void notifyObservers() {//通知观察者
        notifyObservers(null);
    }
    public void notifyObservers(Object arg) {//将arg对象通知每个观察者
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    public synchronized void deleteObservers() {//删除所有观察者
        obs.removeAllElements();
    }
    protected synchronized void setChanged() {//标记被观察者已经改变
        changed = true;
    }
    protected synchronized void clearChanged() {//清除改变
        changed = false;
    }
    public synchronized boolean hasChanged() {//得到改变真假值
        return changed;
    }
    public synchronized int countObservers() {//获取观察者对象
        return obs.size();
    }
}

public interface Observer {
    void update(Observable o, Object arg);
}

根据源码我们考虑,为什么有两个notifyObservers()方法呢,我们观察下这两个的不同点,第一个没有参数,第二个传入了OBJ对象,即一个只是通知观察者我已经发生了改变,至于改变是什么你自己来看(拉模式)。另一个是将整个数据对象全部推送给观察者(推模式)。这样,引言中的疑问我们就解决了。

下面进行上篇博客中天气预报例子的具体实现:

package JAVA内置观察者模式;

import java.util.Observable;

public class WhetherData extends Observable{ //
    private float temp;
    private float humidity;
    private float pressure;
    public WhetherData(){
    }
    public void mesureChanged(){ //气象站气温参数发生变化 调用此接口
        setChanged();//通知之前必须声明改变
	    notifyObservers();
    }
    public void setMeasurements(float temp,float humidity,float pressure){//可以手动设置气温参数
        this.temp=temp;
        this.humidity=humidity;
        this.pressure=pressure;
        mesureChanged();
    }

	public float getTemp(){
		return temp;
	}
	public float getHumidity(){
		return humidity;
	}
	public float getPressure(){
		return pressure;
	}
}
package JAVA内置观察者模式;

public interface DisplayElement {
	public void display();
}

package JAVA内置观察者模式;

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

public class CurrentConditionDisplay implements Observer, DisplayElement {  //具体的观察者
    Observable observable;
	private float temp;
    private float humidity;

    public CurrentConditionDisplay(Observable observable){
	    this.observable=observable;
	    observable.addObserver(this);
    }
    public void update(Observable obs,Object org){
        if(obs instanceof WhetherData){
	        WhetherData whetherData=(WhetherData)obs;
	        this.temp=whetherData.getTemp();
	        this.humidity=whetherData.getHumidity();
	        display();
        }
    }

    public void display(){
        System.out.print("JAVA内置观察者:现在的温度是:"+humidity+"。现在的湿度是:"+temp);
    }
}

package JAVA内置观察者模式;


public class WeatherStation {//入口:气象观测站
    public static  void main(String args[]){
        WhetherData whetherData = new WhetherData();
        CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(whetherData);
        whetherData.setMeasurements(12,15,18);
    }
}

JAVA内置观察者的问题

因为Observable是一个类,我们必须设计子类继承他,而JAVA没有多继承,如果想要同时拥有Observable类和另一个超类的行为,就会很尴尬。而且setChanged()方法是protect,所以想要使用此方法,必须继承父类,设计违反了第二个设计原则:“多用组合,少用继承”。

小结

观察者模式就讲到这里了,在生活中以及JAVA开发中多思考,你会发现处处都是观察者。

作者:select you from me
链接:https://mp.csdn.net/mdeditor/95638512
来源:CSDN
转载请联系作者获得授权并注明出处。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值