(四)23种设计模式之我见-----------观察者模式(Observer)

        设计模式这本书中对观察者模式做了如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。下面我对深入浅出设计模式这本书中的观察者模式,进行自己的理解性剖析。先贴代码,然后对每段代码进行解析,最后画出完整的类图。观察者模式有两个必须的要素就是主题和观察者。在书中,引用了气象站的例子。我们有一个气象站(获取气象数据),有一个weatherData用来收集气象站的数据,并通知布告板做出更新。还有一个布告板系统用来显示收集到的信息。  

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

我们需要定义一个主题接口,体现了面向接口的编程,而不是具体的实现。然后我们需要接着定义观察者的接口

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

        这里需要说明一下主题中,需要有一个方法证明哪些观察者需要被通知,哪些不需要,所以就需要有一个注册方法,类似于一个论坛,你只有注册了,才能享受会员资格。而所有的观察者中就要有一个更新的方法,一旦发生改变就要更新。

        当我们定义一个主题的实现类,用来收集气象站的数据。

import java.util.ArrayList;

public class WeatherData implements Subject {
	private ArrayList observers;
	private float temperature;
	private float humidity;
	private float pressure;
        //构造方法中声明了一个ArrayList用来记录所有注册的观察者
	public WeatherData() {
		observers = new ArrayList();
	}
        //将观察者加入到其中就是注册
	public void registerObserver(Observer o) {
		observers.add(o);
	}
        //删除
	public void removeObserver(Observer o) {
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);
		}
	}
        //通知,从ArrayList中取出数据后调用更新方法
	public void notifyObservers() {
		for (int i = 0; i < observers.size(); i++) {
			Observer observer = (Observer) observers.get(i);
			observer.update(temperature, humidity, pressure);
		}
	}
        //有更新
	public void measurementsChanged() {
		notifyObservers();
	}
        //将更新的数据传出,并告知有更新
	public void setMeasurements(float temperature, float humidity,
			float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}
	// WeatherData的其他方法
}

我们有许许多多的观察者,在此例中我们有许许多多的显示面板,需要显示不同的信息,我们定义了三种不同的面板用以显示不同的信息,每一个具体的实现都要保留一个主题的引用。

public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
 this.weatherData = weatherData;
 weatherData.registerObserver(this);
}
  public void update(float temperature, float humidity, float pressure) {
     this.temperature = temperature;
     this.humidity = humidity;
     display();
}
  public void display() {
     System.out.println("Current conditions: " + temperature
      + "F degrees and " + humidity + "% humidity");
}
}

public class ForecastDisplay implements Observer,DisplayElement{
	private float humidity;
	private Subject weatherData;
	public ForecastDisplay(Subject weatherData) {
		 this.weatherData = weatherData;
		  ((WeatherData) weatherData).registerObserver(this);
		}
	@Override
	public void update(float temp, float humidity, float pressure) {
		this.humidity=humidity;
		display();
	}
	@Override
	public void display() {
		if(this.humidity<=65.0){
			System.out.println("ForeCast : Improving weather on the way!");
		}else if(this.humidity<=80){
	        System.out.println("ForeCast : Watch out for cooler,rainy weather!");
		}else{
			System.out.println("ForeCast : More of the same!");
		}
		
	}
}

public class StatisticsDisplay implements Observer,DisplayElement{
	private float temperature;
	private float humidity;
	private Subject weatherData;
	public StatisticsDisplay(Subject weatherData) {
		
		 this.weatherData = weatherData;
		 weatherData.registerObserver( this);
		}
		  public void update(float temperature, float humidity, float pressure) {
		     this.temperature = temperature;
		     this.humidity = humidity;
		     display();
		}
		  public void display() {
			  if(this.humidity<=65.0){
					System.out.println("Avg/Max/Min temperature = 80.0/80.0/80.0");
				}else if(this.humidity<=80){
			        System.out.println("Avg/Max/Min temperature = 81.0/82.0/80.0");
				}else{
					System.out.println("Avg/Max/Min temperature = 80.0/82.0/78.0");
				}
		}
}

都实现了observer接口和displayelement接口,以方便weatherdata在具体实现的调用,体现了面向接口编程的优越性。

下面我们要写具体的气象站类用来促使整个过程的发生。

public class WeatherStation {
public static void main(String[] args) {
   WeatherData weatherData = new WeatherData();
   CurrentConditionsDisplay currentDisplay =new CurrentConditionsDisplay(weatherData);
   StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
   ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
   weatherData.setMeasurements(80, 65, 30.4f);
   weatherData.setMeasurements(82, 70, 29.2f);
   weatherData.setMeasurements(78, 90, 29.2f);
}
}

这样开始我们的神奇之旅吧。我们在每次调用一个观察者的时候就要进行注册,而注册是在构造函数中进行的,所以需要这么写。发动数据只要进行数据的更新操作即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值