zoukankan      html  css  js  c++  java
  • 学习设计模式之观察者模式

    观察者模式
    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使它们能够自己更新自己。
    **简单点概括就是:**一个类管理着所有依赖于它的观察者类,并且在这个类自身发生变化的时候主动给依赖于它的观察者类发出通知。

    结构图
    类结构图
    Observable
    它把所有的观察者对象引用保存在一个聚集里,每个主题都可以有任何数量的观察者,抽象主题提供一个接口可以增加或删除观察者对象。
    Observer
    抽象观察者,为所有具体观察者定义一个接口,在得到主题的通知时更新自己。
    ConcreteObserver
    具体的观察者。

    代码示例

    public interface Observer {
    
        /**
         * 观察者通知方法
         * @param observable
         */
        void update(Observable observable);
    }
    
    public class ConcreteObserver1 implements Observer {
        @Override
        public void update(Observable observable) {
            System.out.println("观察者1发现 " + observable.getClass().getSimpleName() + " 发生了变化!");
            System.out.println("观察者1收到通知!");
        }
    }
    
    public class ConcreteObserver2 implements Observer {
        @Override
        public void update(Observable observable) {
            System.out.println("观察者2发现 " + observable.getClass().getSimpleName() + " 发生了变化!");
            System.out.println("观察者2收到通知!");
        }
    }
    
    public interface Observable {
        /**
         * 观察者注册
         * @param observer
         */
        void addObserver(Observer observer);
    
        /**
         * 移除观察者
         * @param observer
         */
        void delObserver(Observer observer);
    
        /**
         * 发生变化调用函数
         */
        void changed();
    
        /**
         * 通知观察者
         */
        void notifyObservers();
    }
    
    public class ConcreteObserver implements Observable {
        /**
         * 观察者集合
         */
        private List<Observer> observers = new ArrayList<>();
    
        @Override
        public void addObserver(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void delObserver(Observer observer) {
            observers.remove(observer);
        }
    
        @Override
        public void changed() {
            System.out.println(getClass().getSimpleName() + " 被观察者发生了变化!");
            // 通知所有观察者
            notifyObservers();
        }
    
        @Override
        public void notifyObservers() {
            for (Observer observer : observers) {
                observer.update(this);
            }
        }
    }
    

    客户端示例

    public class Client {
        public static void main(String[] args) {
            Observable observable = new ConcreteObserver();
            observable.addObserver(new ConcreteObserver1());
            observable.addObserver(new ConcreteObserver2());
            observable.changed();
        }
    }
    

    运行结果

    ConcreteObserver 被观察者发生了变化!
    观察者1发现 ConcreteObserver 发生了变化!
    观察者1收到通知!
    观察者2发现 ConcreteObserver 发生了变化!
    观察者2收到通知!
    
    Process finished with exit code 0
    

    我们只要操作被观察者的 changed 方法,具体的观察者们就会做出对应的动作,如果想要被通知到,只需要将观察者注册到被观察者的集合中就可以了。

    观察者所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是具体的实现,从而使得各自的变化都不会影响另一边的变化。在现实编程中具体的观察者有可能是风马牛不相及的类。现在被观察者根本不需要知道观察者是什么类型只需要它实现了观察者接口,而不关心具体的观察者都有谁都是什么类型。

    应用场景
    对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。

    优点
    被观察者和观察者进行了解耦,被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

    缺点
    如果被观察者有很多观察者,将所有的观察者都通知到将会花费多很多时间。

    勿在浮沙筑高台 ——个人浅见,难免有误导之处,麻烦请指出。
  • 相关阅读:
    【Android Developers Training】 73. 布局变化的动画
    【Android Developers Training】 72. 缩放一个视图
    【Android Developers Training】 71. 显示翻牌动画
    svn更改地址怎么办
    python学习手册
    failed to bind pixmap to texture
    Ubuntu 12.04安装Google Chrome
    svn update 时总是提示 Password for '默认密钥' GNOME keyring: 输入密码
    重设SVN 的GNOME keyring [(null)] 的密码
    Nginx + uWSGI + web.py 搭建示例
  • 原文地址:https://www.cnblogs.com/liufeichn/p/11961646.html
Copyright © 2011-2022 走看看