观察者模式 设计模式学习笔记(二)

    技术2022-07-11  122

    观察者模式

    简介:

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

    角色:主题和观察者。

    观察者订阅主题,主题的数据发生变化时,通知到所有的观察者更新数据。

    在书中是使用的更新布告板数据的例子。

    当气象站的数据(温度,湿度,气压)发生变化时,布告板的数据也发生相应的变化。

    实现需求:观察者接口、观察者实现类、主题接口、主题实现类。

    代码实现:

    主题接口:

    public interface Subject { //注册观察者 void registerObserver(Observer observer); //删除观察者 void removeObserver(Observer observer); //通知其他观察者并更新观察者数据 void notifyObservers(); }

    观察者接口

    public interface Observer { //更新观察者数据 void update(float temp,float humidity,float pressure); }

    主题实现类

    import java.util.ArrayList; //主题实现类 public class WeatherData implements Subject { private float temp; private float humidity; private float pressure; //记录所有订阅过主题的观察者 ArrayList<Observer> observers; //在构造器中初始化观察者集合 public WeatherData() { observers = new ArrayList<>(); } @Override public void registerObserver(Observer observer) { //注册一个观察者 observers.add(observer); } @Override public void removeObserver(Observer observer) { //删除一个观察者 observers.remove(observer); } @Override public void notifyObservers() { //更新所有订阅过主题的观察者的数据 for (int i = 0; i < observers.size(); i++) { observers.get(i).update(temp, humidity, pressure); } } //改变主题的值并更新观察者的值 public void setMeasurements(float temp, float humidity, float pressure){ this.temp = temp; this.humidity = humidity; this.pressure = pressure; notifyObservers(); } }

    观察者实现类

    public class ForecastDisplay implements Observer { private float temp; private float humidity; private float pressure; //记录订阅过的主题 private Subject subject; //在构造器中订阅主题 public ForecastDisplay(Subject subject) { this.subject = subject; subject.registerObserver(this); } @Override public void update(float temp, float humidity, float pressure) { this.temp = temp; this.humidity = humidity; this.pressure = pressure; } @Override public String toString() { return "ForecastDisplay{" + "temp=" + temp + ", humidity=" + humidity + ", pressure=" + pressure + ", subject=" + subject + '}'; } }

    测试类

    public class ObserverTest { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); //注册观察者,有观察者的代码几乎都一致。 CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); weatherData.setMeasurements(80,65,30.4f); System.out.println("CurrentConditionsDisplay:" + currentConditionsDisplay); System.out.println("StatisticsDisplay:" + statisticsDisplay); System.out.println("ForecastDisplay:" + forecastDisplay); weatherData.setMeasurements(65,80,23.4f); System.out.println("CurrentConditionsDisplay:" + currentConditionsDisplay); System.out.println("StatisticsDisplay:" + statisticsDisplay); System.out.println("ForecastDisplay:" + forecastDisplay); } }

    运行结果

    CurrentConditionsDisplay:CurrentConditionsDisplay{temp=80.0, humidity=65.0, pressure=30.4, subject=WeatherData@1540e19d} StatisticsDisplay:StatisticsDisplay{temp=80.0, humidity=65.0, pressure=30.4, subject=WeatherData@1540e19d} ForecastDisplay:ForecastDisplay{temp=80.0, humidity=65.0, pressure=30.4, subject=WeatherData@1540e19d} CurrentConditionsDisplay:CurrentConditionsDisplay{temp=65.0, humidity=80.0, pressure=23.4, subject=WeatherData@1540e19d} StatisticsDisplay:StatisticsDisplay{temp=65.0, humidity=80.0, pressure=23.4, subject=WeatherData@1540e19d} ForecastDisplay:ForecastDisplay{temp=65.0, humidity=80.0, pressure=23.4, subject=WeatherData@1540e19d}

    总结:

    在代码中其实可以看到,我们在所有的方法参数上声明的都是观察者接口和主题接口,这样一来可以有效的降低代码之间的耦合。因为在传递参数的时候,我们不需要知道这个观察者或者主题是怎么样实现的。如果我们想要更多的观察者或者主题,我们也不需要去改变原来的代码,只需要让一个具体类去实现主题或者观察者接口,同时我们也不需要关注具体的方法是如何实现的,就可以进行订阅、删除、更新等功能,大大的降低了代码之间的耦合。

    Processed: 0.009, SQL: 9