设计模式一:观察者模式

观察者模式

本文摘自:《Head First 设计模式》

观察者模式= 出版者+订阅者。定义了对象之间的一对多依赖,当一个对象改变状态时,所有依赖者都收到通知并更新。最好示例如:微信公众号和用户,微信用户可以关注和取消关注某公众号,公号更新内容时通知所有订阅者。这里的公众号对应观察者模式的“主题”(subject),微信用户即“观察者”(Observer)。

观察者模式对象

主题

  • 观察者订阅
  • 观察者取消订阅
  • 有新数据时通知所有订阅者

观察者

  • 接受主题通知

类图

示例:气象观察站

主题接口

public interface Subject {
    public void registerObserver(Observer o);

    public void removeObeserver(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 temperature;
    private float humidity;
    private float pressure;

    public WeatherData(){
        observers = new ArrayList();
    }
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }
    @Override
    public void remoteObeserver(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 observer = (Observer) observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }
    public void measurementsChanged(){
        notifyObserver();
    }
    public void setMeasurements(float temperature, float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;

        measurementsChanged();
    }
}

观察者类

public class CurrentConditionDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private Subject weatherData;

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

    @Override
    public void update(float temp, float humidity, float pressure) {
        // udate 被调用时,把数据保存其阿里
        this.temperature = temp;
        this.humidity = humidity;
        display();
    }

    @Override
    public void display() {
        //把最近的温度和湿度展示出来
        System.out.println("Current conditions: " + temperature +
        "F degrees and " + humidity + "% humidty");
    }
}

测试

public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionDisplay currentConditionDisplay =
                new CurrentConditionDisplay(weatherData);
        weatherData.setMeasurements(80, 65, 33.4f);
    }

Current conditions: 80.0F degrees and 65.0% humidty

设计原则

  1. 找出程序中会变化的方面,然后将其和固定不变的方面分离
  2. 针对接口编程,不针对实现编程
  3. 多用组合,少用继承
  4. 为交互对象之间的松耦合设计而努力
CONTENTS