观察者模式(Observer Patterns)

今天学习了观察者模式,做个总结,方便以后回想。

首先是定义:观察者模式就是定义对象之间一对多的依赖关系,当一个对象状态发生改变时,全部依赖他的对象都收到推送消息并自己主动更新做出改变。

我的理解:生活中就有非常多这种样例,比如气象观測站和气象显示仪的关系,气象显示站是数据中心,负责获得最新的气象消息,而气象显示仪则把即使的消息显示出来,全部的气象显示仪都依赖气象站,还有求职者和猎头公司的关系,猎头公司假设有新的信息,也会推送给求职者;这里气象站就是主题(中心),显示仪就是观察者。

个人感觉假设要用到观察者模式一定要用到面向接口编程的设计原则,要定义Subject接口来注冊,取消,推送;定义Observer接口来update,假设观察者还有其它功能,还要写其它的接口,比如display()的接口。

首先是Subject接口:提供了注冊,取消注冊,推送消息的方法。

package interfaces;


public interface Subject {
	
	public void registeObserver (Observer observer);
	public void removeObserver (Observer observer);
	//notify:通知,公告
	public void notifyObserver ();
	
}


然后是Observer接口,提供了更新操作,把获取到的数据更新到本地实例数据。

package interfaces;

public interface Observer {
	public void uodate (float temp, float humidity, float pressure);
}


然后是DisplayElement接口,提供了display方法。

package interfaces;

public interface DisplayElement {
	public void display();
}

然后是WeatherData,天气信息数据中心类,实现Subject接口,并提供了setMeasurements方法和measurmentChanged方法,观察者注冊的实现事实上就是把这个观察者加到中心的List里面,通知操作就是遍历List,都调用里面的update方法。

package subjects;

import java.util.ArrayList;
import java.util.List;

import interfaces.Observer;
import interfaces.Subject;

public class WeatherData implements Subject {
	private List list;
	private float temperature;
	private float humidity;
	private float pressure;
	
	public WeatherData() {
		list = new ArrayList();
	}

	@Override
	public void registeObserver(Observer observer) {
		list.add(observer);
	}

	@Override
	public void removeObserver(Observer observer) {
		int i = list.indexOf(observer);
		if(i>=0) {
			list.remove(i);
		}
	}

	@Override
	public void notifyObserver() {
		for(int i=0;i<list.size();i++) {
			Observer o = (Observer)list.get(i);
			o.uodate(temperature, humidity, pressure);
		}

	}
	
	public void measurementsChanged() {
		notifyObserver();
	}
	
	public void setMeasures(float temp, float humidity, float pressure) {
		this.temperature = temp;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}

}


然后定义了一个观察者CurrentConditionDisplay。新建的时候就要传递一个数据中心。

package observers;

import subjects.WeatherData;
import interfaces.DisplayElement;
import interfaces.Observer;
import interfaces.Subject;

public class CurrentConditionDisplay implements Observer, DisplayElement {
	private float tempurature;
	private float humidity;
	private float pressure;
	private Subject weatherData;
	
	public CurrentConditionDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registeObserver(this);
	}

	@Override
	public void uodate(float tempurature, float humidity, float pressure) {
		this.tempurature = tempurature;
		this.humidity = humidity;
		this.pressure = pressure;
		display();

	}

	@Override
	public void display() {
		System.out.println(tempurature + ";/n" + humidity + ";/n"  +pressure );
		
	}

}

最后是一个測试类:

package test;

import observers.CurrentConditionDisplay;
import subjects.WeatherData;

public class Test {
	
	public static void main(String args[]) {
		WeatherData weatherData = new WeatherData();
		CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
		
		weatherData.setMeasures(14.1f, 11.0f, 111.0f);
	}
}

事实上Java的Swing机制大量运用了这样的模式,比如button和监视器的关系,button是被观察者,监视器是观察者,addListener的时候事实上就是把监视器对象放到了自己的list内,点击的时候就调用list里面的监视器的performXX方法。


尽管仅仅是通过样例了解并练习了,可是能不能在以后实际项目中想到用到,是否熟练等,任重而道远。

原文地址:https://www.cnblogs.com/bhlsheji/p/4374027.html