head first 设计模式:观察者模式1

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,他的所有者就会立刻接到通知并自动更新。
观察者模式定义了一系列对象之间的一对多关系。
当一个对象改变状态,当其他依赖者都会收到通知。

实现观察者模式的方法不止一种,但是以包含Subject与Observer接口的类的设计最为常见。

这和一对多的关系有何关联?
利用观察者模式,主题是具有状态的对象,并且可以控制这些状态。也就是说,有“一个”具有状态的主题。
另一方面,观察者使用这些状态,虽然这些状态并不属于他们。有许多的观察者,依赖主题来告诉他们状态
何时改变了。这就产生了一个关系:“一个”主题对“多个”观察者的关系。

期间的依赖是如何产生的?
因为主题是真正拥有数据的人,观察者是主题的依赖者,在数据变化更新,这样比起让许多对象控制一份数据来,可以得到更干净OO设计。

设计原则:为了交互对象之间的松耦合设计而努力


Demo:

业务场景:

建立一个应用,有三种布告板,分别显示目前的状况、气象统计及简单的预报。
当WeatherObject对象获得最新的测量数据时,三种布告板必须实时更新。

这是一个可以扩展的气象站,其他开发人员可以写出自己的气象布告板,并插入到应用中。

package cn.partner4java.weather;


/**
 * 主业务类(管理观察员、并负责调用观察员)
 * @author partner4java
 *
 */
public interface Subject {
	
	/**
	 * 注册观察员
	 * @param observer 观察员
	 */
	public void registerObserver(Observer observer);
	
	/**
	 * 删除观察员
	 * @param observer 观察员
	 */
	public void removeObserver(Observer observer);
	
	/**
	 * 通知所有的观察者
	 */
	public void notifyObserver();
}

package cn.partner4java.weather;


/**
 * 布告板
 * (如:目前状况布告板、统计布告板、预测布告板)
 * @author partner4java
 *
 */
public interface DisplayElement {
	
	/**
	 * 布告调用方法
	 */
	public void display();

}

package cn.partner4java.weather;


/**
 * 观察员(气象发生改变时,被调用的对象)
 * @author partner4java
 *
 */
public interface Observer {
	/**
	 * 所有的观察者都必须实现这个方法,以实现观察者接口
	 * @param temperature 温度
	 * @param humidity 湿度
	 * @param pressure 气压
	 */
	public void update(float temperature,float humidity,float pressure);
}

package cn.partner4java.weather.impl;

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

import cn.partner4java.weather.Observer;
import cn.partner4java.weather.Subject;


/**
 * 气象数据获取类
 * 主业务类(管理观察员、并负责调用观察员)
 * 实现主体接口
 * @author partner4java
 *
 */
public class WeatherData implements Subject {
	/** 观察者列表 */
	private List<Observer> observers;
	/** 温度 */
	private float temperature;
	/** 湿度 */
	private float humidity;
	/** 气压 */
	private float pressure;
	
	public WeatherData(){
		observers = new ArrayList<Observer>();
	}
	
	@Override
	public void notifyObserver() {
		for(int i=0;i<observers.size();i++){
			Observer observer = observers.get(i);
			observer.update(temperature, humidity, pressure);
		}
	}

	@Override
	public void registerObserver(Observer observer) {
		int i = observers.indexOf(observer);
		if(i == -1){
			observers.add(observer);
		}
	}

	@Override
	public void removeObserver(Observer observer) {
		int i = observers.indexOf(observer);
		if(i >= 0){
			observers.remove(i);
		}
	}
	
	
	/**
	 * 当从气象站得到更新观测值时,我们通知观察者
	 */
	public void measurementsChanged(){
		notifyObserver();
	}

	
	/**
	 * 设置气象改变数据
	 * @param temperature 温度
	 * @param humidity 湿度
	 * @param pressure 气压
	 */
	public void setMeasurements(float temperature,float humidity,float pressure){
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	
	}
	
	
	public List<Observer> getObservers() {
		return observers;
	}

	public void setObservers(List<Observer> observers) {
		this.observers = observers;
	}

	public float getTemperature() {
		return temperature;
	}

	public void setTemperature(float temperature) {
		this.temperature = temperature;
	}

	public float getHumidity() {
		return humidity;
	}

	public void setHumidity(float humidity) {
		this.humidity = humidity;
	}

	public float getPressure() {
		return pressure;
	}

	public void setPressure(float pressure) {
		this.pressure = pressure;
	}
	
	

}

package cn.partner4java.weather.impl;

import cn.partner4java.weather.DisplayElement;
import cn.partner4java.weather.Observer;
import cn.partner4java.weather.Subject;


/**
 * 目前状况布告板
 * @author partner4java
 *
 */
public class CurrentConditionsDisplay implements Observer, DisplayElement {
	private float temperature;
	private float humidity;
	private Subject weatherData;
	
	public CurrentConditionsDisplay(Subject weatherData){
		this.weatherData = weatherData;
		this.weatherData.registerObserver(this);
	}
	
	@Override
	public void update(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		display();
	}

	@Override
	public void display() {
		System.out.println("CurrentConditionsDisplay: temperature-" + temperature +  
				" humidity-" + humidity);
	}

}

package cn.partner4java.weather.impl;

import cn.partner4java.weather.DisplayElement;
import cn.partner4java.weather.Observer;


/**
 * 未来天气预告版
 * @author partner4java
 *
 */
public class ForecastDisplay implements DisplayElement, Observer {
	/** 当前气压 */
	private float currentPressure = 29.92f;  
	/** 最后一次气压 */
	private float lastPressure;
	private WeatherData weatherData;
	
	
	public ForecastDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}
	
	@Override
	public void display() {
		System.out.print("Forecast: ");
		if (currentPressure > lastPressure) {
			System.out.println("Improving weather on the way!");
		} else if (currentPressure == lastPressure) {
			System.out.println("More of the same");
		} else if (currentPressure < lastPressure) {
			System.out.println("Watch out for cooler, rainy weather");
		}
	
	}

	@Override
	public void update(float temperature, float humidity, float pressure) {
		lastPressure = currentPressure;
		currentPressure = pressure;
		display();
	}

}
package cn.partner4java.weather.impl;

import cn.partner4java.weather.DisplayElement;
import cn.partner4java.weather.Observer;


/**
 * 统计状态布告
 * @author partner4java
 *
 */
public class StatisticsDisplay implements DisplayElement, Observer {
	/** 最高温度 */
	private float maxTemp = 0.0f;
	/** 最低温度 */
	private float minTemp = 200;
	/** 记录总温度 */
	private float tempSum = 0.0f;
	/** 温度读取次数 */
	private int countReadings;
	private WeatherData weatherData;
	
	public StatisticsDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}
	
	@Override
	public void display() {
		System.out.println("StatisticsDisplay: maxTemp-" + 
				maxTemp + " minTemp-" + minTemp + " averageTemp-" + 
				tempSum/countReadings);
		
	}

	@Override
	public void update(float temperature, float humidity, float pressure) {
		tempSum += temperature;
		countReadings++;
		if(temperature < minTemp){
			minTemp = temperature;
		}else if(temperature > maxTemp){
			maxTemp = temperature;
		}
		display();
	}

}


package cn.partner4java.weather.test;

import cn.partner4java.weather.impl.CurrentConditionsDisplay;
import cn.partner4java.weather.impl.ForecastDisplay;
import cn.partner4java.weather.impl.StatisticsDisplay;
import cn.partner4java.weather.impl.WeatherData;


/**
 * 气象站测试(启动气象站)
 * @author partner4java
 *
 */
public class WeatherStation {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();
		CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
		StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
		ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
		
		weatherData.setMeasurements(80, 234, 20.4f);
		weatherData.setMeasurements(56, 232, 20.4f);
		weatherData.setMeasurements(34, 123, 20.4f);
		
	}

}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值