首页 > 代码库 > 观察者模式

观察者模式

目的:用WeatherData对象从气象台取得数据并更新布告板,考虑系统的可扩展性,满足随心所欲添加或删除布告板。如图所示:

 

考虑在同一时刻只选择一个布告板并显示的情况。抽取中其中改变的部分,即布告板。设想实现如下图:

上图设计中可以满足弹性的任意选择一个布告板并对其进行更新。然而我们需要的是有多个布告板能显示不同的

内容并显示更新。解决问题的方法:WeatherData中需要有一个容器来缓存多个布告板,但是并不是所有的布告

板都需要进行更新显示。WeatherData只对那些有需要更新并显示的布告板进行通知并更新他们。所以引出了观察

者模式,这相当于一个订阅问题,每个布告板都是一个观察者,Weather是一个主题。观察者对主题感兴趣则对主题

进行订阅。当观察者对主题不再感兴趣时者取消订阅主题,即做到了任意添加或删除布告板。当主题改变时,所有订

阅主题的观察者都将被通知。

实现图如下:

实现代码:

主题接口:

public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}

观察者接口:

public interface Observer {
public void update(float temperature,float pressure,float humidy);
public void register(Subject weatherData);
public void cancel();
}

显示接口:

public interface DisplayElement {
public void display();
}

WeatherData类:

public class WeatherData implements Subject{
private float temperature;
private float pressure;
private float humidy;
private List observers;
public WeatherData(){
observers=new ArrayList();
}
@Override
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
observers.remove(o);
}
@Override
public void notifyObservers() {
// TODO Auto-generated method stub
for(int i=0;i<observers.size();i++)
{
Observer o=(Observer)observers.get(i);
o.update(temperature,pressure,humidy);
}
}
public void measurementsChanged()
{
notifyObservers();
}
public void setMeasurements(float temperature,float pressure,float humidy)
{
this.temperature=temperature;
this.pressure=pressure;
this.humidy=humidy;
measurementsChanged();
}

}

布告板1:

public class CurrentConditionDisplay implements Observer, DisplayElement{
private float temperature;
private float pressure;
private float humidy;
private Subject weatherData;

public CurrentConditionDisplay()
{}
public CurrentConditionDisplay(Subject weatherData)
{
this.weatherData=http://www.mamicode.com/weatherData;
weatherData.registerObserver(this);
}
@Override
public void display()
{
// TODO Auto-generated method stub
System.out.println("Current conditions: ");
System.out.println(temperature+"F degrees");
System.out.println(pressure+"%pressure");
System.out.println(humidy+"%humidy");
}
@Override
public void update(float temperature,float pressure,float humidy)
{
// TODO Auto-generated method stub
this.temperature=temperature;
this.pressure=pressure;
this.humidy=humidy;
display();
}
@Override
public void register(Subject weatherData) {
// TODO Auto-generated method stub
this.weatherData=http://www.mamicode.com/weatherData;
weatherData.registerObserver(this);
}
@Override
public void cancel() {
// TODO Auto-generated method stub
weatherData.removeObserver(this);
}

}

布告板2:

public class AverageConditionDisplay implements Observer,DisplayElement{
private float temperature;
private float pressure;
private float humidy;
Subject weatherData;
public AverageConditionDisplay()
{}
public AverageConditionDisplay(Subject weatherData)
{
this.weatherData=http://www.mamicode.com/weatherData;
weatherData.registerObserver(this);
}

@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("average conditions: ");
System.out.println(temperature+"F degrees");
System.out.println(pressure+"%pressure");
System.out.println(humidy+"%humidy");
}

@Override
public void update(float temperature, float pressure, float humidy) {
// TODO Auto-generated method stub
if(this.temperature==0)
{
this.temperature=temperature;
}
else
{
this.temperature=(this.temperature+temperature) / 2;
}
if(this.pressure==0)
{
this.pressure=pressure;
}
else
{
this.pressure=(this.pressure+pressure) / 2;
}
if(this.humidy==0)
{
this.humidy=humidy;
}
else
{
this.humidy=(this.humidy+humidy) / 2;
}
display();
}

@Override
public void register(Subject weatherData) {
// TODO Auto-generated method stub
this.weatherData=http://www.mamicode.com/weatherData;
weatherData.registerObserver(this);
}

@Override
public void cancel() {
// TODO Auto-generated method stub
weatherData.removeObserver(this);
}

}

气象模拟类:

public class WeatherStation {
public static void main(String [] args)
{
WeatherData weatherData=http://www.mamicode.com/new WeatherData();
//CurrentConditionDisplay ccd=new CurrentConditionDisplay(weatherData);
//AverageConditionDisplay acd=new AverageConditionDisplay(weatherData);
CurrentConditionDisplay ccd=new CurrentConditionDisplay();
ccd.register(weatherData);
AverageConditionDisplay acd=new AverageConditionDisplay();
acd.register(weatherData);
weatherData.setMeasurements(80, 30.4f, 65);
weatherData.setMeasurements(60, 28.2f, 35);
//weatherData.removeObserver(acd);
acd.cancel();
weatherData.setMeasurements(90, 32.4f, 62);
}
}