观察者模式2

来源:互联网 发布:南风知我意下载 编辑:程序博客网 时间:2024/05/17 09:28

观察者模式


·让对象能够在状态改变时被通知
·观察者模式:
    ·观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
    ·主题和观察者之间松耦合:
        ·主题只知道观察者实现了某个接口(Observer接口),而不需要知道观察者的具体类是什么及其他细节
        ·任何时刻都可以为主题增加新的观察者或删除某些观察者

·基本描述:
    ·一个主题接口或者一个主题基类
        ·使用接口来扩展可被观察性的话,缺陷在于不同的主题都得去实现接口的方法,代码复用性差
        ·使用主题基类来赋予子类可被观察性的话,缺陷在于子类无法同时继承并复用其他类的特性
            ·存放观察者的列表
            ·标识主题是否更新的标志及对应设置移除方法
            ·增加移除观察者的方法
            ·通知观察者主题有更新的方法(调用观察者接口的对应方法将更新传递给观察者)    
    ·相关的可被观察主题(实现上述接口或继承上述类)
    ·一个观察者接口
        ·获取更新的方法
    ·若干观察者(实现观察者接口)

--------------------------

// 观察者接口
public interface IObserver {
    void update(Observable subject, Object arg);
}

--------------------------

/** 可被观察的类需要继承的基类 */
public class Observable {
    
    // 标识被观察的主题类是否已经更新
    private boolean changed = false;
    // 存放观察者
    private Vector obs;

    public Observable() {
        obs = new Vector();
    }

    public synchronized void addObserver(IObserver o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    public synchronized void deleteObserver(IObserver o) {
        obs.removeElement(o);
    }

    public void notifyObservers() {
        notifyObservers(null);
    }

    
    public void notifyObservers(Object arg) {
        
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length - 1; i >= 0; i--)
            ((IObserver) arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

--------------------------

/** 可被观察的主题类 */
public class WeatherData extends Observable{

    private float temperature;    // 温度
    private float humidity;        // 湿度
    private float pressure;        // 压力
    
    // 主题数据变化,通知观察者
    public void measurementsChanged(){
        setChanged();
        notifyObservers();
    }
    
    // 主题数据更新
    public void setMeasurements(float temperature, float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
    
    
}

--------------------------

public interface IDisplayElement {
    void display();
}

--------------------------

// 观察者之二
public class TemperatureConditionDisplay implements IDisplayElement, IObserver {

    private String condition;

    public TemperatureConditionDisplay(Observable sub){
        sub.addObserver(this);
    }
    
    @Override
    public void display() {
        System.out.println("today, " + condition);

    }

    @Override
    public void update(Observable subject, Object arg) {

        if(subject instanceof WeatherData){
            WeatherData temp = (WeatherData)subject;
        
            switch((int)temp.getTemperature()/10){
            case -3:case -2:case -1:
                condition = "very cold!"; break;
            case 0:
                condition = "cold!"; break;
            case 1:
                condition = "a little cold!"; break;
            case 2:
                condition = "cool!"; break;
            case 3:
                condition = "a little hot!"; break;
            case 4:
                condition = "hot!"; break;
            case 5:
                condition = "very hot!"; break;
            default:
                condition = "you will be dead!"; break;
            }
            
            display();
        }
    }

}

--------------------------

// 观察者之一
public class CurrentConditionDisplay implements IObserver, IDisplayElement {
    
    private float temperature;    // 温度
    private float humidity;        // 湿度
    private Observable subject;        // 观察的主题对象引用
    
    // 向欲观察的主题对象注册自己
    public CurrentConditionDisplay(Observable subject){
        this.subject = subject;
        subject.addObserver(this);
    }

    // 获取主题的更新
    @Override
    public void update(Observable subject, Object arg) {
        if(subject instanceof WeatherData){
            WeatherData temp = (WeatherData)subject;
            this.temperature = temp.getTemperature();
            this.humidity = temp.getHumidity();
            display();
        }    
    }

    @Override
    public void display() {
        System.out.println("Current Condition:"+temperature+"℃ and "+humidity+"% humidity.");
    }

}

--------------------------

public class Demo {

    public static void main(String[] args) {
        
        // 主题对象
        WeatherData weatherData = new WeatherData();
        // 初始化观察者并向主题注册
        IObserver ob1 = new CurrentConditionDisplay(weatherData);
        IObserver ob2 = new TemperatureConditionDisplay(weatherData);
        
        // 主题更新数据
        weatherData.setMeasurements(37.0F, 20.0F, 1000.0F);
        weatherData.setMeasurements(317.0F, 20.0F, 1000.0F);

    }

}

--------------------------

0 0
原创粉丝点击