您的位置:首页 > 其它

设计模式之观察者模式(Observer)

2014-08-11 18:09 309 查看
1、定义

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并启动更新。

2、类图





Subject被观察者:定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。

Observer观察者:观察者接收到消息后即进行update(更新操作),对接收到的信息进行处理

ConcreteSubject具体的被观察者:定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。

ConcreteObserver具体的观察者:每个观察者在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。

3、问题描述

现在有一个气象站的对象,此对象负责对几个终端输送信息。气象站即可称为主题,而终端即为观察者。气象站和终端是一对多的依赖,当气象站状态改变时,所有终端都会收到通知并启动更新。代码如下:

package observer;
/**
* 主题
*/
public interface Subject {
public void registerObServer(Observer o);
public void removeObServer(Observer o);
public void notifyObservers();
}

package observer;
/**
* 观察者
*/
public interface Observer {
public void update(float temp,float humidity,float pressure);
}

package observer;

import java.util.ArrayList;

public class WeatherData implements Subject{

private ArrayList<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public  WeatherData(){
observers=new ArrayList<Observer>();
}
public void registerObServer(Observer o) {//注册观察者
observers.add(o);
}
@Override
public void removeObServer(Observer o) {//删除观察者
observers.remove(o);
}
@Override
public void notifyObservers() {
for(Observer ob:observers){
ob.update(temperature, humidity, pressure);
}
}

public void measuermentsChanged(){
notifyObservers();
}

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 observer;

public class CurrentConditionsDisplay implements Observer{

public void update(float temp, float humidity, float pressure) {
System.out.println("current conditions:"+temp);
}
}

package observer;

public class WeatherStation {
public static void main(String a[]){
WeatherData weatherData=new WeatherData();
Observer currentDisplay=new CurrentConditionsDisplay();
weatherData.setHumidity(12);
weatherData.setPressure(23);
weatherData.setTemperature(344);
weatherData.registerObServer(currentDisplay);
weatherData.measuermentsChanged();
}
}

以上完美解决了气象台状态改变后改变其他终端数据的问题。但是这种模式是“推”数据方式,将数据从subject推到observer中。但是有时候终端并不需要所有的状态,终端希望自己主动从subject“拉”数据。在java API中有内置的观察者模式。java.util包内包含最基本的Observer接口和Observable类。可以使用推(push)或拉(pull)的方式传送数据。


使用java API的观察者模式的拉模式,代码如下:

package observer;

import java.util.ArrayList;
import java.util.Observable;
/**
* 集成JAVA API中的Observeable(可观察者)类
*/
public class WeatherData extends Observable{

private float temperature;
private float humidity;
private float pressure;
public  WeatherData(){
}

public void measurementsChanged(){
setChanged();//指示状态已经改变
notifyObservers();//使用拉数据方式
}

public void setMeasuerments(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}

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 observer;

import java.util.Observable;

public class CurrentConditionsDisplay implements java.util.Observer{
Observable observable;
private float temperature;
private float humidity;

public CurrentConditionsDisplay(Observable observable){
this.observable=observable;
observable.addObserver(this);
}

@Override
public void update(Observable obs, Object arg) {
if(obs instanceof WeatherData){
WeatherData weatherData=(WeatherData)obs;
this.temperature=weatherData.getTemperature();
this.humidity=weatherData.getHumidity();
System.out.println("Current Conditions:"+this.temperature);
}

}
}

package observer;

import java.util.Observable;

public class WeatherStation {
public static void main(String a[]){
WeatherData weatherData=new WeatherData();
weatherData.setMeasuerments(12,13, 14);
java.util.Observer currentDisplay=new CurrentConditionsDisplay(weatherData);
currentDisplay.update(weatherData, null);
}
}

java API中的observable使用类而不是接口,不可取。实际中可以自行设计主题和观察者,不使用java api中提供的方式。


在JDK中,Swing大量使用观察者模式,许多GUI框架也是如此。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: