观察者模式

观察者模式

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

这个模式很好理解,就是多个观察者类观察一个具体的主题,当这个主题改变时,所有的观察者就都知道了这一改变,当某个观察者不再观察这个主题时,则不会注意到这个改变。例如我们生活中的订阅或关注,当你订阅了某个杂志或者关注了某个公众号后,当这个公众号有内容更新,即推送信息时,就会通知你,此时一个公众号就是一个主题,每个用户就是观察者。当你不再关注某个公众号时,则不会再通知你该公众号的相关文章。

案例

这里给出一个案例代码,这是一个对天气实时监控的模拟,当空气中环境变化时,展示板中的内容就会更新,不同的展示板可能可以展示不同的信息,这里只给出一个实例。

主题:在主题中需要有相应的注册观察者,删除观察者,通知观察者的方法

/**
 * 观察者模式中的主题
 *
 */
public interface Subject {
    /**
     * 用于注册观察者
     * @param o
     */
    public void registerObserver(Observer o);
    /**
     * 用于删除观察者
     * @param o
     */
    public void removeObserver(Observer o);
    /**
     * 用于通知所有的观察者
     */
    public void notifyObserver();
}

观察者:

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

一个展示板的基础接口:

public interface DisplayElement {
    public void display();
}

具体的主题:

/**
 * 一个具体的主题,当发生变化则会通知所有观察者
 *
 */
public class WeatherData implements Subject {
    private ArrayList observers;
    private float temp,humidity,pressure;


    public WeatherData() {
        observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if(i >= 0)
            observers.remove(i);
    }

    @Override
    public void notifyObserver() {
        for(int i=0;i<observers.size();i++) {
            Observer o = (Observer) observers.get(i);
            o.update(temp, humidity, pressure);
        }
    }
    /**
     * 当数据更新时调用,用以通知所有的观察者
     */
    public void measurementsChanged() {
        notifyObserver();
    }

    public void setMeasurements(float temp, float humidity, float pressure) {
        this.temp = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
    //其他方法
}

具体的观察者:

/**
 * 一个具体的观察者
 *
 */
public class CurrentConditionsDisplay implements Observer,DisplayElement{
    private float temp;
    private float humidity;
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("Current conditions: " + temp
                + "F degrees and " + humidity + "% humidity");
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temp = temp;
        this.humidity = humidity;
        display();
    }

}

测试

public class Test {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay display = new CurrentConditionsDisplay(weatherData);
        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(83, 75, 29.4f);
        weatherData.setMeasurements(81, 68, 31.4f);
    }
}

结果:

Current conditions: 80.0F degrees and 65.0% humidity
Current conditions: 83.0F degrees and 75.0% humidity
Current conditions: 81.0F degrees and 68.0% humidity

这样就实现了当某个主题发生变化时,观察者就能够知道这一变化,通过注册观察者能够实现添加订阅功能,而删除观察者则可以实现取消关注/订阅等功能。

-------------本文结束感谢您的阅读-------------