观察者模式

Updated on with 0 views and 0 comments

观察者模式

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

Java 实现

使用 Java 内置的观察者模式

可观察者继承Observable(java.util.Observable)
观察者实现Observer(java.util.Observer)接口

缺点

  • Observable是一个类
    • 如果某类想同时具有Observable类和另一个超类的行为,就会陷入两难,毕竟Java不支持多重继承。这限制了Observable的复用潜力。
    • 因为没有Observable接口,所以无法建立自己的实现,和Java内置的Observer API搭配使用,也无法将java.util的实现换成另一套做法的实现
  • Observable将关键的方法保护起来
    • setChanged()方法被保护起来了。这意味着:除非你继承自Observable,否则你无法创建Observable实例并组合到你自己的对象中来。这个设计违反了第二个设计原则:多用组合,少用继承。

自己实现

可观察者

接口

public interface Subject {

    /**
     * 功能描述: 注册观察者
     *
     * @param o 观察者
     * @return void
     * @author liyf
     */
    void registerObserver(Observer o);

    /**
     * 功能描述: 删除观察者
     *
     * @param o 观察者
     * @return void
     * @author liyf
     */
    void removeObserver(Observer o);

    /**
     * 功能描述: 通知所有的观察者
     *
     * @param
     * @return void
     * @author liyf
     */
    default void notifyObserver() {
        notifyObserver(null);
    }

    /**
     * 功能描述: 通知所有的观察者
     *
     * @param arg 推送的数据
     * @return void
     * @author liyf
     */
    void notifyObserver(Object arg);

    /**
     * 功能描述: 标记被观察者对象已经改变
     *
     * @param
     * @return void
     * @author liyf
     */
    void setChanged();

    /**
     * 功能描述:清除改变状态
     *
     * @param
     * @return void
     * @author liyf
     */
    void clearChanged();

    /**
     * 功能描述: 查询被观察者对象是否改变
     *
     * @param
     * @return boolean
     * @author liyf
     */
    boolean hasChanged();
}

实现

被观察者应只有一个,所以使用了单例模式

public class WeatherStation implements Subject {

    private WeatherData weatherData;
    private boolean changed = false;
    private List<Observer> list = new ArrayList<>();

    private WeatherStation() {
    }

    private static class SingletonHolder {
        private static final WeatherStation INSTANCE = new WeatherStation();
    }

    public static WeatherStation getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 功能描述: 当气象站更新数据时,通知观察者
     *
     * @param
     * @return void
     * @author liyf
     */
    public void measurementsChanged() {
        setChanged();
        notifyObserver(weatherData);
    }

    /**
     * 功能描述: 更新数据
     *
     * @param weatherData 天气数据
     * @return void
     * @author liyf
     */
    public void setMeasurements(WeatherData weatherData) {
        this.weatherData = weatherData;
        measurementsChanged();
    }

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

    @Override
    public void removeObserver(Observer o) {
        list.remove(o);
    }

    @Override
    public void notifyObserver(Object arg) {
        if (changed) {
            for (Observer observer : list) {
                observer.update(this, arg);
            }
        }
    }

    @Override
    public void setChanged() {
        changed = true;
    }

    @Override
    public void clearChanged() {
        changed = false;
    }

    @Override
    public boolean hasChanged() {
        return changed;
    }


}

观察者

接口

public interface Observer {

    /**
     * 功能描述:
     *
     * @param subject 被观察者
     * @param arg 参数
     * @return void
     * @author liyf
     */
    void update(Subject subject, Object arg);
}

实现

public class CurrentConditionsDisplay implements Observer, DisplayElement {

    private WeatherData weatherData;
    private Subject subject;

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

    @Override
    public void display() {
        System.out.println("CurrentConditionsDisplay.weatherData = " + weatherData);
    }

    @Override
    public void update(Subject subject, Object arg) {
        if (subject instanceof WeatherStation) {
            this.weatherData = (WeatherData) arg;
            display();
        }
    }
}
public class StatisticsDisplay implements Observer, DisplayElement {

    private WeatherData weatherData;
    private Subject subject;

    public StatisticsDisplay(Subject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("StatisticsDisplay.weatherData = " + weatherData);
    }

    @Override
    public void update(Subject subject, Object arg) {
        if (subject instanceof WeatherStation) {
            this.weatherData = (WeatherData) arg;
            display();
        }
    }
}

测试

public class TestWeatherStation {

    @Test
    public void test() {
        WeatherStation weatherStation = WeatherStation.getInstance();
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherStation);
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherStation);

        WeatherData weatherData = new WeatherData(80, 65, 30.4f);

        weatherStation.setMeasurements(weatherData);

        weatherData.setHumidity(70);
        weatherStation.setMeasurements(weatherData);
    }
}

结果

CurrentConditionsDisplay.weatherData = WeatherData(temperature=80.0, humidity=65.0, pressure=30.4)
StatisticsDisplay.weatherData = WeatherData(temperature=80.0, humidity=65.0, pressure=30.4)
CurrentConditionsDisplay.weatherData = WeatherData(temperature=80.0, humidity=70.0, pressure=30.4)
StatisticsDisplay.weatherData = WeatherData(temperature=80.0, humidity=70.0, pressure=30.4)