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

时间:2021-05-27 11:55:21

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

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

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

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

出版和订阅的关系:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Subject(主题)接口:

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

Observer(观察者接口):

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

DisplayElement(布告板)接口:

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

(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); }
}

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