zoukankan      html  css  js  c++  java
  • 第二章 观察者模式

    现在我们要做一个天气应用程序,可以显示当前的天气状况。你需要从气象台获取数据,然后显示在公告板上。气象台的数据随时都有可能变化,你的公告板也需要同步变化。

    image

    我们可以让公告板每隔一段时间查询一次天气数据。为了不错过重要数据,这个时间间隔要小一些(也许每隔一秒)。同时又为了节约资源,这个时间间隔又要设大一些(也许每小时一次)。这样就很矛盾。本质问题在于你不能预测什么时候有新数据产生。

    这就好像你忙着工作不能经常查阅自己的电子邮箱。然而不经常查阅邮箱可能会错过很多重要的邮件。怎么办呢?如果有新邮件到来都会提醒我就好了!对,这就是观察者模式。

    谈到观察者模式前,我们要约定一个术语:主题(subject)。观察者对主题很感兴趣,希望主题有变动后都会收到提醒。主题发生变化后会主动提醒所有关注它的观察者,而不关心观察者收到最新的数据后会做些什么。

     

    用观察者模式来设计我们的天气应用

    WeatherData是主题(Subject),CurrentConditionsDisplay(天气公告板)是观察者(Observer)。

    主题能够注册、注销观察者,当数据发生变化时还要通知所有已经注册的观察者。

    观察者主要等着主题来通知自己就好(等主题调用自己的update方法)。

    image

    主题代码

    public interface Subject {
        public void registerObserver(Observer observer);
        public void removeObserver(Observer observer);
        public void notifyObservers();
    }
    
    public class WeatherData implements Subject {
        private float temperature;//温度
        private float humidity;//湿度
        private float pressure;//压力
        private 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 (Observer observer : observers) {
                observer.update(temperature, humidity, pressure);
            }
        }
        
        //在合适的时候通知所有观察者
        public void measurementsChanged() {
            notifyObservers();
        }
        
        //数据发送变化,这时候需要通知所有观察者
        public void setMeasurements(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChanged();
        }
    }

    观察者代码

    public interface Observer {
        public void update(float temperature, float humidity, float pressure);
    }
    
    public interface DisplayElement {
        public void display();
    }
    
    public class CurrentConditionsDisplay implements DisplayElement, Observer {
        private float temperature;
        private float humidity;
        private float pressure;
        
        @Override
        public void update(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            
            display();
        }
    
        @Override
        public void display() {
            System.out.println("###温度公告板###");
            System.out.println("温度:" + temperature);
            System.out.println("湿度:" + humidity);
            System.out.println("气压:" + pressure);
            System.out.println("############");
        }
    }

    客户端代码

    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        Observer observer = new CurrentConditionsDisplay();
        
        weatherData.registerObserver(observer);
        weatherData.setMeasurements(3.3f, 5.5f, 6.6f);
        weatherData.removeObserver(observer);
        weatherData.setMeasurements(11.5f, 55.2f, 10.8f);
    }

    输出://你会看到只有一个输出,因为观察者被注销了,就没收到“通知”。

    ###当前温度公告板###
    温度:3.3
    湿度:5.5
    气压:6.6
    ############

     

    Java内置的观察者模式API

    Java内置了:

    • java.util.Observable,可以被观察的东西(就是主题啦)
    • java.util.Observer,观察者

    具体用法这里不展开。但是Java内置的API确实存在一些问题:

    • Observable是一个类,如果你的WeatherData同时要继承自另一个基类,那就不能继承Observable了。Java不支持多重继承。
    • 我们提倡“多用组合,少用继承”。很可惜我们不能通过对象组合来使用Observable,因为Observable的一个很关键的setChanged()是protected方法。

    Java的API也有不少缺点,那怎么办呢?

    • Observable是一个类,这大大降低编程新手的使用门槛,因为关键代码已经实现在基类里面了,你只要继承就好。也就是说你不需要了解观察者模式也能借助Java API使用它。其实即是缺点也是优点。
    • 既然你已经学会了观察者模式,那可以自己实现,不要用Java的API。反正也不难。

    观察者模式的应用

    这个应用很多,比如Android里面Button.setOnClickListener(…);

  • 相关阅读:
    double相加(減)结果会有些误差
    创建表,操作表
    删除数据库
    DDL语句
    HCDA-12-配置基本静态路由
    HCDA-11-配置直连路由
    1-5配置STelnet登录系统
    HCDA-9-管理设备文件系统
    HCDA-8-了解设备系统文件
    Java生成随机汉字
  • 原文地址:https://www.cnblogs.com/dongchen/p/5014813.html
Copyright © 2011-2022 走看看