knot

导航

设计模式二之观察者模式(Subject-Observer)

观察者模式定义了一系列对象之间的一对多关系,当一个主题对象改变状态,其他所有的依赖者都会收到通知。

好了,你可能会觉得上面的描述略微复杂,较难理解,那么现在我们将用一个简单的例子去讲解这个模式。

我们先来分析出版和订阅的关系:

出版和订阅的关系:

(1) 一家出版公司,负责每天按时出版报纸

(2) 很多个用户订阅报纸,每天会收到出版社出版的报纸内容,用户可以订阅(注册),也可以取消订阅(注销注册信息)。

(3) 出版社和用户之间的关系是一(出版社)对多(用户)的关系,并且用户依赖出版社出版的报纸,以实现对自身信息数据的刷新。

(4) 我们将出版社看成主题,将用户看成观察者,整个过程就是一个 主题---观察者模式,也就是 Subject--Observer模式。

这就是最简单的观察者模式,简单理解了之后,我们来做一个气象站,需求如下:

(1) 我们需要实现一个气象站

(2) 有一个 WearherData 对象负责追踪 温度,湿度和气压的变化

(3) 有很多种不同类型(WeatherObject)的布告板,用来显示当前的天气状况,布告板必须实时更新

分析以上三个条件,可以知道 WeatherData 和 WeatherObject 存在一对多的关系,并且多个 WeatherObject 依赖 WeatherData 进行数据的刷新。

将整个过程采用观察者模式来进行分析:

 

接下来,我们用代码实现上面的图:

(1) 3个接口,一个Subject (主题接口), 一个 Observer(观察者接口),一个DisplayElement(布告板接口)

 

Subject(主题)接口:

Observer(观察者接口):

DisplayElement(布告板)接口:

 

(2) 实现主题(Subject)接口的WeatherData类:

 

public class WeatherData implements Subject{

    private float tempture;
    private float pressure;
    private float humity;
    List<Observer> observers;
    public WeatherData() {
        observers = new ArrayList<Observer>();
    }
    @Override
    public void registerObserver(Observer obv) {
        // TODO Auto-generated method stub
        //注册方法中将需要注册的观察者加到List中
        observers.add(obv);
    }

    @Override
    public void removeObserver(Observer obv) {
        // TODO Auto-generated method stub
        //注销方法中将需要注销的观察者移除
        int i = observers.indexOf(obv);
        if(i>=0)
        {
            observers.remove(i);
        }
    }

    @Override
    public void NotifyAllObserver() {
        // TODO Auto-generated method stub
        //通知所有观察者进行数据的刷新
        for(int i=0 ;i<observers.size(); i++)
        {
            //获取到每一个观察者的对象,把该对象的所有属性值改变就行
            Observer observer = (Observer)observers.get(i);
            observer.update(tempture, humity, pressure);
        }
    }
    
    public void SetMesurements(float tempture, float humity, float pressure)
    {
        this.humity = humity;
        this.pressure = pressure;
        this.tempture = tempture;
        MeasurementChanged();
    }
    private void MeasurementChanged() {
        // TODO Auto-generated method stub
        NotifyAllObserver();
    }

}

 

 (3) 现在就可以任意画自己想要的布告板了:

public class CurrentConditionDisplay implements Observer, DisplayElement {

	private float tempture;
	private float humidity;
	private float pressure;
	private Subject WeatherData;
	@Override
	public void display() {
		// TODO Auto-generated method stub
		//展示布告板
		System.out.println(tempture+""+humidity+""+pressure);
	}

	@Override
	public void update(float temp, float humidity, float pressure) {
		// TODO Auto-generated method stub
		this.humidity = humidity;
		this.tempture = temp;
		this.pressure = pressure;
		display();
	}

	public CurrentConditionDisplay(Subject weatherData)
	{
		//在构造方法中注册观察者
		this.WeatherData = weatherData;
		WeatherData.registerObserver(this);
	}
}

 

(4) 最后,写一个测试类,测试我们画好的布告板:

public class projectTestClass {

	public static void main(String[] args)
	{
		WeatherData weathData = new WeatherData();
		CurrentConditionDisplay ss = new CurrentConditionDisplay(weathData);
		weathData.SetMesurements(10, 10, 10);
		
	}
}

 这就是整个观察者模式的处理过程。

 

posted on 2018-01-16 19:27  knot  阅读(232)  评论(0编辑  收藏  举报