Java设计模式之观察者模式(一)

2014-11-24 01:19:46 · 作者: · 浏览: 2

Java设计模式之观察者模式

摘要:观察者模式(ObserverPattern)。用于实时监测某些Object的动态、只要Object一改变、那么他的所有观察者Observer都会知道、之后观察者会根据Object的改变进行下一步操作。这个在SWING编程中是最常见的。那些Listener就是观察者。

一:问题的引出

要实现一个天气预报的功能、当天气的数据发生变化的时候、会实时的以三种形式来显示天气:当前天气情况、统计分析情况、天气预报。有可能还会有第四种显示。

这里我们不管数据是如何来的、就假设我们已经能获取到数据了。在程序中是通过调用被观察的对象的notifyObserver方法来通知所有Observer来实现的。

二:问题分析

1、通过分析我们得出一个简单的总结:就是天气数据一旦有更新、那么就要实时的改变显示。观察者模式可以很好的解决这种模型的问题。

2、既然确定要使用观察者模型、就要定位出谁是观察者、谁是被观察者、这里有个简单的原则、观察者与被观察者之间的关系是多对一的关系、也就是说被观察者只有一个、那么就是我们的天气数据信息、观察者则是三种要显示不同信息的终端(当然也可以有第四个观察者)。

3、因为每个观察者都要动态的显示信息、所以我们应该抽象出来一个显示信息的类或者接口。

4、既然角色分工很清除了、接下来就是设计、与组装了。

5、考虑到可扩展性、低耦合、灵活性、和对扩展开放、对修改关闭的原则和面向接口编程、我们下面具体话类的设计。

6、根据角色我们可以抽象出三个接口:

a) 所有被观察者的接口――Subject;

b) 所有观察者的接口――Observer;

c) 显示信息的接口――DisplayElement;

7、对于Subject当然要拥有三个关于操作Observer的方法、注册、移除、和通知Observer的方法(观察者肯定要和被观察者结合起来)。

8、对于Observer肯定要有一个update方法、就是一旦检测到Subject有变动、就更新信息、所以还要实现DisplayElement接口。

二:具体实现

1、设计Subject接口:

package com.chy.dp.observer;

public interface Subject {
	public void registerObserver(Observer observer);
	public void removeObserver(Observer observer);
	public void notifyObserver();
}

2、设计Observer接口:

package com.chy.dp.observer;

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

3、设计DisplayElement接口:

package com.chy.dp.observer;

public interface DisplayElement {
	public void display();
}

4、设计具体的实现Subject接口的被观察者――WeatherDate

package com.chy.dp.observer;

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

public class WeatherDate implements Subject {

	// Observer数组 可以简单想一下为什么不用LinkedList
	private List
  
    observers = new ArrayList
   
    (); private float temperature; private float humidity; private float pressure; @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { int index = observers.indexOf(observer); if (index >= 0) { observers.remove(observer); } } @Override public void notifyObserver() { for (int i = 0; i < observers.size(); i++) { Observer o = (Observer) observers.get(i); o.update(temperature, humidity, pressure); } } /** * 模仿数据变动时自动触发notifyObserver函数 */ public void measurementsChanged() { notifyObserver(); } /** * 模仿数据变动、即当我们调用这个方法时就说明数据有改变、 这样所有的观察者都会被通知 */ public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } }
   
  

5、接下来就是实现我们的观察者Observer的具体实现――CurrentConditionDisplay:

package com.chy.dp.observer;

public class CurrentConditionDisplay implements DisplayElement, Observer {
	private float temperature;
	private float humidity;
	private Subject weatherDate;
	
	
	/**
	 * 将被观察者通过构造方法传递进来、并将此观察者注册到被观察者中
	 * 这样观察者和被观察者就完美的结合了
	 * @param weatherDate
	 */
	public CurrentConditionDisplay(Subject weatherDate) {
		super();
		this.weatherDate = weatherDate;
		this.weatherDate.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("Current comditions : " + temperature + " F degrees and " + humidity + "% humidity");
	}
}


6、同样的、关于显示ForecastConditionDisplay、StatisticsDisplay代码与上面非常相似。

7、Client:

package com.chy.dp.observer;

@SuppressWarnings("unused")
public class Client {
	public static void main(String[] args) {
		WeatherDate subject = new WeatherDate();
		
		ForecastConditionDisplay fcd = new ForecastConditionDisplay(subject);
		
		CurrentConditionDisplay ccd = new CurrentConditionDisplay(subject);