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

    应用场景


    定义对象间的一对多关系,使得一个对象的状态发生改变的时候其他对象会被通知到并自动更新,这和我们现实中的广播是一个道理。

    类图关系


    类图关系如下所示

    Subject:被观察者,一般被定义为抽象类。它能够动态的增加、取消观察者,在被观察者与观察者属于聚合的关系,被观察者能够调用观察者的更新方法来通知观察者自己的装发生改变。

    ConcreteSubject:具体的观察者,定义自己的业务逻辑,控制当那些事情发生了进行通知

    Observer:提供更新接口来供被观察者调用

    ConcreteObserver:每个观察者收到消息后处理反应是不同的,各个观察者应该有自己具体的处理逻辑

    示例代码


    被观察者

    abstract class Subject{
        //定义一个观察者组
        private Vector<Observer> observers = new Vector<>();
        
        public void addObject(Observer o){
            this.observers.add(o);
        }
        
        public void delObject(Observer o){
            this.observers.remove(o);
        }
        //通知所有的观察者
        public void notifyObserver(){
            for(Observer o:this.observers)
                o.update();
        }
    }

    具体被观察者

    class ConcreteSubject extends Subject{
        public void doSomething(){
            //实现具体的业务并通知观察者
            super.notifyObserver();
        }
    }

    观察者

    interface Observer{
        public void update(); 
    }

    具体观察者

    class ConcreteObserver implements Observer{
    
        @Override
        public void update() {
            System.out.println("接收到信息...");
        }
        
    }

    场景类

    class client{
        public static void main(String[] args) {
            //定义一个被观察者
            ConcreteSubject cs = new ConcreteSubject();
            //定义三个观察者
            Observer co1 = new ConcreteObserver();
            Observer co2 = new ConcreteObserver();
            Observer co3 = new ConcreteObserver();
            //将三个观察者进行注册
            cs.addObject(co1);
            cs.addObject(co2);
            cs.addObject(co3);
            //被观察者开始活动
            cs.doSomething();;
        }
    }

    总结


    有点:容易扩展,建立一套有效的触发机制

    缺点:效率问题,一个被观察者和多个被观察者开发和调试就会比较复杂。

    注意:当观察者模式应用到广播链中时需要注意链的长度不宜过长。它和责任链最大的区别是广播链在传播的过程中消息是随时可以更改的;责任链模式下消息的传递基本保持不变。

    java库中也提供了相应的观察模式实现接口java.util.Observable和java.util.Observer

  • 相关阅读:
    tar解压时如何去掉第一级目录并解压到指定目录?
    ubuntu下容器无法启动报错"failed to start daemon: failed to dial "/run/containerd/containerd.sock": unknown service containerd.services.namespaces.v1.Namespaces: not implemented"如何处理?
    redis用法介绍
    Map.putAll()用法
    Random,ThreadLocalRandom,SecureRandom的几点思考
    SOAPUI---使用断言
    AutoUpdater迁移到Github
    VirtualBox: linux 没有权限访问共享文件夹的问题
    MakeFIle: 解决“/bin/bash^M: bad interpreter: No such file or directory”的问题
    ubuntu 备忘录
  • 原文地址:https://www.cnblogs.com/xidongyu/p/5815365.html
Copyright © 2011-2022 走看看