观察者模式

920 阅读1分钟

概念

定义对象间的一对多的关系,使得当一个对象改变状态,所有依赖于它的对象都会得到通知并自动更新。优点是被观察者和观察者是抽象耦合,提高系统灵活性,缺点是开发调试变复杂,而且java消息通知默认是顺序执行,一个观察者卡顿会影响整体执行效率,所以一般采取异步形式。

使用场景

  • 关联行为场景(不是组合)
  • 事件多级触发场景
  • 跨系统消息交换,如消息队列,事件总线的处理机制

实现方式

  • Subject —— 抽象主题:被观察者角色(Observable),将所有观察者对象的引用保存在集合中,提供可以增加删除观察者的接口。
  • ConcreteSubject —— 具体主题 具体被观察者
  • Observer —— 抽象观察者 定义一个更新接口,使得在在主题状态改变时及时通知自己更新状态。
  • ConcreteObserver —— 具体观察者 Observer 和 Observable是JDK的内置类型,因此,我们可以直接编写具体实现类
    /**
     * 抽象被观察者
     **/
    interface Observable {
        //注册观察者
        void registerObserver(Observer observer);

        //解除绑定观察者
        void unRegisterObserver(Observer observer);

        //更新数据
        void notifyObservers();
    }

    /**
     * 抽象观察者
     */
    interface Observer {
        void update(Observable observable, Object value);
    }

    /**
     * 具体被观察者
     **/
    public class MyView implements Observable {
        List<Observer> observerList;
        private int progress;

        public MyView() {
            this.observerList = new ArrayList<>();
        }

        @Override
        public void registerObserver(Observer observer) {
            if (observerList.contains(observer)) {
                return;
            }
            observerList.add(observer);
        }

        @Override
        public void unRegisterObserver(Observer observer) {
            int i = observerList.indexOf(observer);
            if (i >= 0) {
                observerList.remove(observer);
            }
        }

        @Override
        public void notifyObservers() {
            for (Observer observer : observerList) {
                observer.update(this, progress);
            }
        }

        public void setProgress(int progress) {
            this.progress = progress;
            notifyObservers();
        }
    }

    /**
     * 具体观察者
     */
    public class ProgressListener implements Observer {
        @Override
        public void update(Observable observable, Object value) {
            System.out.println("progress = " + value);
        }
    }

    public static void main(String[] args) {
        MyView myView = new MyView();
        Observer progressListener = new ProgressListener();
        myView.registerObserver(progressListener);
        myView.setProgress(10);
    }