• 设计模式之观察者模式


    1. 观察者模式概述

    在这里插入图片描述

    观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象可以同时监听并收到被观察对象的状态变化通知,以保持对象之间的数据同步。
    观察者模式涉及以下角色:

    1. 主题(Subject):也叫做被观察者,维护一组观察者对象,提供方法用于注册和删除观察者,以及通知观察者更新状态。
    2. 观察者(Observer):定义一个更新方法,用于在主题状态改变时接收通知。观察者可以注册到一个或多个主题。
    3. 具体主题(Concrete Subject):实现主题接口,负责维护观察者列表,并在状态改变时通知观察者。
    4. 具体观察者(Concrete Observer):实现观察者接口中的更新方法,以实际响应主题状态变化。

    在这里插入图片描述

    观察者模式的优点包括:

    1. 松散耦合:主题和观察者之间的关系是松散的,它们互不依赖,可以独立变化。

    2. 可复用性:可以在同一主题上注册不同的观察者,以实现不同的业务逻辑。

    3. 扩展性:可以随时添加新的观察者,不需要修改现有的代码。

    观察者模式在实际应用中非常常见,例如在GUI开发中用于处理用户界面和数据之间的关系,事件处理机制、消息队列等。
    总之,观察者模式允许对象之间建立一种松散的耦合关系,当一个对象的状态发生变化时,它可以通知多个观察者,从而实现对象间的协同工作。

    2. Java实现观察者模式

    2.1 以天气预报为场景

    • 首先,我们定义观察者接口 Observer 和主题接口 Subject:
    import java.util.List;
    
    // 观察者接口
    interface Observer {
        void update(String weather);
    }
    
    // 主题接口
    interface Subject {
        void registerObserver(Observer observer);
        void removeObserver(Observer observer);
        void notifyObservers();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 接下来,创建具体的观察者 WeatherObserver 和具体的主题 WeatherStation:
    import java.util.ArrayList;
    import java.util.List;
    
    // 具体观察者
    class WeatherObserver implements Observer {
        private String name;
    
        public WeatherObserver(String name) {
            this.name = name;
        }
    
        @Override
        public void update(String weather) {
            System.out.println(name + " 收到天气变化通知:" + weather);
        }
    }
    
    // 具体主题
    class WeatherStation implements Subject {
        private List<Observer> observers = new ArrayList<>();
        private String weather;
    
        public void setWeather(String weather) {
            this.weather = weather;
            notifyObservers();
        }
    
        @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(weather);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 现在我们可以创建观察者并让它们订阅主题的通知:
    public class Main {
        public static void main(String[] args) {
            WeatherStation weatherStation = new WeatherStation();
    
            WeatherObserver observer1 = new WeatherObserver("Observer 1");
            WeatherObserver observer2 = new WeatherObserver("Observer 2");
            WeatherObserver observer3 = new WeatherObserver("Observer 3");
    
            weatherStation.registerObserver(observer1);
            weatherStation.registerObserver(observer2);
            weatherStation.registerObserver(observer3);
    
            weatherStation.setWeather("晴天");
            weatherStation.setWeather("下雨");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    当我们运行这段代码时,观察者们将会接收到主题天气变化的通知,并打印出相应的信息。这就是观察者模式的应用示例。在实际场景中,主题可以是任何需要通知观察者的对象,而观察者可以是需要订阅主题通知的各种组件或对象。

    2.2 一个对象的状态变化通知多个对象:在线股票交易

    • 首先,我们定义观察者接口 Observer 和主题接口 Subject:
    import java.util.List;
    
    // 观察者接口
    interface Observer {
        void update(String stockName, double stockPrice);
    }
    
    // 主题接口
    interface Subject {
        void registerObserver(Observer observer);
        void removeObserver(Observer observer);
        void notifyObservers();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 接下来,创建具体的观察者 StockObserver 和具体的主题 StockMarket:
    import java.util.ArrayList;
    import java.util.List;
    
    // 具体观察者
    class StockObserver implements Observer {
        private String name;
    
        public StockObserver(String name) {
            this.name = name;
        }
    
        @Override
        public void update(String stockName, double stockPrice) {
            System.out.println(name + " 收到股票 " + stockName + " 的价格更新,当前价格为 " + stockPrice);
        }
    }
    
    // 具体主题
    class StockMarket implements Subject {
        private List<Observer> observers = new ArrayList<>();
        private String stockName;
        private double stockPrice;
    
        public void setStockInfo(String stockName, double stockPrice) {
            this.stockName = stockName;
            this.stockPrice = stockPrice;
            notifyObservers();
        }
    
        @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(stockName, stockPrice);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 现在我们可以创建观察者并让它们订阅主题的通知:
    public class Main {
        public static void main(String[] args) {
            StockMarket stockMarket = new StockMarket();
    
            StockObserver observer1 = new StockObserver("Investor 1");
            StockObserver observer2 = new StockObserver("Investor 2");
            StockObserver observer3 = new StockObserver("Investor 3");
    
            stockMarket.registerObserver(observer1);
            stockMarket.registerObserver(observer2);
            stockMarket.registerObserver(observer3);
    
            stockMarket.setStockInfo("ABC", 100.0);
            stockMarket.setStockInfo("XYZ", 75.5);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    当股票价格发生变化时,观察者们会收到通知并打印出新的股票价格信息。这是另一个观察者模式的应用示例。观察者模式非常适合在需要解耦主题和观察者的情况下实现通知机制。

  • 相关阅读:
    既然测试也要求写代码,那干脆让开发兼任测试不就好了吗?
    Python+Requests+PyTest+Excel+Allure 接口自动化测试实战
    YARP:探索反向代理的新境界
    【c语言的函数指针介绍】
    Is BCP able to connect db with semicolon(or special charactors) in the password
    第十一章《搞懂算法:聚类是怎么回事》笔记
    随笔--ubuntu解压zip乱码问题
    Qt,C++中QString,string,char数组等常用格式转换大总结
    【技术积累】算法中的贪心算法【一】
    C++实践2:在c++20中为spdlog与fmt装配source_location
  • 原文地址:https://blog.csdn.net/m0_54187478/article/details/133967016