• [学习记录] 设计模式 3. 观察者模式


    观察者模式

    参考:

    当一个行为发生时传递信息给另外一个用户接收做出相应的处理,两者之间没有直接的耦合关联。

    在我们编程开发中也会常用到一些观察者的模式或者组件,例如我们经常使用的MQ服务,虽然MQ服务是有一个通知中心并不是每一个类服务进行通知,但整体上也可以算作是观察者模式的思路设计。再比如可能有做过的一些类似事件监听总线,让主线服务与其他辅线业务服务分离,为了使系统降低耦合和增强扩展性,也会使用观察者模式进行处理。

    1. 结构

    在这里插入图片描述

    2. 实现

    2.1 Obverse 和 Obversable

    该方式已经在 Java 9 被弃用

    This class and the Observer interface have been deprecated. The event model supported by Observer and Observable is quite limited, the order of notifications delivered by Observable is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using the java.beans package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in the java.util.concurrent package. For reactive streams style programming, see the java.util.concurrent.Flow API.

    2.1.1 被观察者

    当被观察者的 state 变化时,通知所有进制的观察者。

    public class Subject extends Observable {
        private int state;
    
        public int getState() {
            return state;
        }
    
        public void setState(int state) {
            this.state = state;
            this.setChanged();
            this.notifyObservers();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    2.1.2 多个观察者
    public class BinaryObserver implements Observer {
        public BinaryObserver(Observable observable) {
            observable.addObserver(this);
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof Subject) {
                System.out.println("Binary String: " + Integer.toBinaryString(((Subject) o).getState()));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class OctalObserver implements Observer {
        public OctalObserver(Observable observable) {
            observable.addObserver(this);
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof Subject) {
                System.out.println("Binary String: " + Integer.toOctalString(((Subject) o).getState()));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class HexaObserver implements Observer {
        public HexaObserver(Observable observable) {
            observable.addObserver(this);
        }
    
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof Subject) {
                System.out.println("Binary String: " + Integer.toHexString(((Subject) o).getState()));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    2.1.3 测试
    public class Test{
        public static void main(String[] args) {
            Subject subject = new Subject();
            new BinaryObserver(subject);
            new OctalObserver(subject);
            new HexaObserver(subject);
            System.out.println("First state change: 15");
            subject.setState(15);
            System.out.println("Second state change: 10");
            subject.setState(10);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    还值得优化的部分:可以把添加观察者还有删除观察者的功能提取到一个单独的管理类中。

    2.2 PropertyChangeEvent,PropertyChangeSupport,PropertyChangeListener

    这三个类分别对应的职责:

    • PropertyChangeListener:观察者
    • PropertyChangeSupport:管理者
    • PropertyChangeEvent:事件
    class EventSource {
    
        private String name;
        /*
         * 在事件源的地方添加一个PropertyChangeSupport对象,间接地由它负责添加监听、激发事件
         */
        private final PropertyChangeSupport listeners = new PropertyChangeSupport(this);
    
        /**
         * 在事件源上添加监听,实际上是在PropertyChangeSupport对象上添加监听
         */
        public void addListener(PropertyChangeListener listener) {
            listeners.addPropertyChangeListener(listener);
        }
    
        /**
         * 同上
         */
        public void removeListener(PropertyChangeListener listener) {
            listeners.removePropertyChangeListener(listener);
        }
    
        /**
         * 事件源发生变化时,也是通过PropertyChangeSupport对象把事件发送到监听者上的
         */
        public void setName(String name) {
            String oldValue = this.name;
            this.name = name;
            // 触发事件源,监听者得到触发变化
            listeners.firePropertyChange("name", oldValue, this.name);
        }
    }
    
    @Slf4j
    class Monitor implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            log.info("事件源 {} 发生变化, {} ==> {}", evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
        }
    }
    
    public class TestPropertyChangeSupport {
        public static void main(String[] args) {
            EventSource eventSource = new EventSource();
            Monitor monitor = new Monitor();
            //在事件源上添加监听,发生变化时就会调用propertyChange方法
            eventSource.addListener(monitor);
            eventSource.setName("11");
        }
    }
    
    • 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
    • 48
    • 49
    • 50
  • 相关阅读:
    操作系统知识点-处理机调度
    【大数据分析专业之基于python的企业数据大屏可视化分析系统-哔哩哔哩】 https://b23.tv/hUraRJV
    0基础学习VR全景平台篇 第95篇:VR实景智慧导航操作手册
    Windows远程桌面连线显示请稍后
    Next.js和sharp实现占位图片生成工具
    【云原生】SpringCloud-Spring Boot Starter使用测试
    工具篇 | 07 | maven
    HTML
    jupyter报错解决方案 : 无法将“jupyter”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
    一文搞懂 Vue3 defineModel 双向绑定:告别繁琐代码!
  • 原文地址:https://blog.csdn.net/qq_39906884/article/details/133069862