设计原则
为了交互对象之间的松耦合设计而努力
观察者模式
在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新
我们定义了一个主题接口和一个观察者接口,外加一个展示数据的接口
主题接口主要包括注册观察者,移除观察者和有修改以后内容推送给观察者
我们的观察者是随时可以加入,随时可以离开的
而我们的观察者接口主要实现的是数据的接收和更新
package Observer;
public interface Subject {
public void registerObserver(Object o);
public void removeObserver(Object o);
public void notifyObserve();
}
package Observer;
public interface Observe {
public void update(float temp, float humidity, float pressure);
}
package Observer;
public interface DisplayElement {
public void display();
}
package Observer;
import java.util.ArrayList;
public class WeatherDate implements Subject{
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherDate() {
observers = new ArrayList();
}
@Override
public void registerObserver(Object o) {
observers.add(o);
}
@Override
public void removeObserver(Object o) {
int i = observers.indexOf(o);
if (i > 0)
observers.remove(i);
}
@Override
public void notifyObserve() {
for (int i = 0; i < observers.size(); i++) {
Observe observe = (Observe) observers.get(i);
observe.update(temperature, humidity, pressure);
}
}
public void measurementsChanged(){
notifyObserve();
}
public void setMeasurements(float temperature, float humidity, float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
并且我们还定义了四个展示板
展示板中都含有一个对主题对象的引用,用来注册这个观察者
当我们调用主题者的setMeasurements()方法之后,进而会调用measurementsChanged()和notifyObserve()
最后将会把更新的内容推送到每一个观察者
package Observer;
/**
显示当前的温度和湿度的展示板
**/
public class CurrentConditionsDisplay implements Observe, DisplayElement{
private float temperature;
private float humidity;
private Subject weatherDate;
public CurrentConditionsDisplay(Subject weatherDate) {
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
@Override
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
package Observer;
/**
显示当前湿度的适宜程度展示板
**/
public class ForecastDisplay implements Observe, DisplayElement {
private float curPre = 29.92f;
private float lastPre = 0;
private WeatherDate weatherDate;
public ForecastDisplay(WeatherDate weatherDate) {
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
lastPre = curPre;
curPre = humidity;
display();
}
@Override
public void display() {
System.out.print("Forecast: ");
if (curPre > lastPre) {
System.out.println("Improving weather on the way!");
} else if (curPre == lastPre) {
System.out.println("More of the same");
} else if (curPre < lastPre) {
System.out.println("Watch out for cooler, rainy weather");
}
}
}
package Observer;
/**
显示当前酷热度展示板
**/
public class HeatIndexDisplay implements Observe, DisplayElement {
private float heatIndex = 0;
private WeatherDate weatherDate;
public HeatIndexDisplay(WeatherDate weatherDate) {
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
heatIndex = computeHeatIndex(temp, humidity);
display();
}
private float computeHeatIndex(float t, float rh) {
float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh)
+ (0.00941695 * (t * t)) + (0.00728898 * (rh * rh))
+ (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +
(0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 *
(rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) +
(0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +
0.000000000843296 * (t * t * rh * rh * rh)) -
(0.0000000000481975 * (t * t * t * rh * rh * rh)));
return index;
}
@Override
public void display() {
System.out.println("Heat index is " + heatIndex);
}
}
package Observer;
/**
显示当前温度最大最小和平均值的展示板
**/
public class StatisticsDisplay implements Observe, DisplayElement{
private float max = 0.0f;
private float min = 200;
private float sum = 0.0f;
private int num = 0;
private WeatherDate weatherDate;
public StatisticsDisplay(WeatherDate weatherDate) {
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
sum += temp;
num++;
if (temp < min){
min = temp;
}
if (temp > max){
max = temp;
}
display();
}
@Override
public void display() {
System.out.println("Avg/Max/Min temperature = " + (sum / num)
+ "/" + max + "/" + min);
}
}
最后是测试
package Observer;
public class WeatherStation {
public static void main(String[] args) {
WeatherDate weatherDate = new WeatherDate();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherDate);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherDate);
ForecastDisplay forecastDisplay = new ForecastDisplay(weatherDate);
HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherDate);
weatherDate.setMeasurements(80, 65, 30.4f);
weatherDate.setMeasurements(82, 70, 29.2f);
weatherDate.setMeasurements(10, 10, 29.2f);
}
}
测试结果