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

    首先了解下观察者模式的概念;

    观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态的时候,它的所有依赖者都会受到通知并自动更新;

    上面的概念比较抽象,其实观察者模式也叫发布订阅模式,可以这样理解,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。

    我们先来看看看Observable类的源码:

    public class Observable {
        
        private boolean changed = false;
        //观察者集合
        private Vector<Observer> obs;
    
        public Observable() {
            obs = new Vector<>();
        }
    
        //添加观察者
        public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
            if (!obs.contains(o)) {
                obs.addElement(o);
            }
        }
        //删除观察者
        public synchronized void deleteObserver(Observer o) {
            obs.removeElement(o);
    
        public void notifyObservers() {
            notifyObservers(null);
        }
    
        //通知所有观察者
        public void notifyObservers(Object arg) {
            Object[] arrLocal;
    
            synchronized (this) {
                if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
    
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        }
        //删除所有观察者
        public synchronized void deleteObservers() {
            obs.removeAllElements();
        }
        //开启通知观察者权限
        protected synchronized void setChanged() {
            changed = true;
        }
        //恢复关闭权限
        protected synchronized void clearChanged() {
            changed = false;
        }
        //查询权限
        public synchronized boolean hasChanged() {
            return changed;
        }
       //观察者数量
        public synchronized int countObservers() {
            return obs.size();
        }
    }

    再来看看Observer接口的源码:

    public interface Observer {
    //更新观察者内容
    void update(Observable o, Object arg); }

    下面了做个简单小测试。

    定义目标类,继承Observable类:

    public class MySubject extends Observable{
        
        //目标需要通知观察者的内容
        private String msg;
        
        public void set(String s) {        
            this.msg=s;
            //setChanged()将changed状态改为true
            setChanged();
            //在changed改为true后才能通知所有观察者
            notifyObservers(msg);    
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    定义观察者类,实现Observer接口:

    public class ObjectA implements Observer {
        private String msg;
        
        @Override
        public void update(Observable o, Object arg) {
            //装换目标类并获取目标类需要通知的内容
            msg=((MySubject)o).getMsg();        
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    下面就开始测试,观察者可以是多个:

    public class Test {
        public static void main(String[] args) {
            //创建目标对象
            MySubject ms=new MySubject();
            
            //创建观察者对象
            ObjectA obj1=new ObjectA();
            ObjectA obj2=new ObjectA();
            ObjectA obj3=new ObjectA();
            
            //addObserver(obj)是Suject类自带的添加观察者方法
            ms.addObserver(obj1);
            ms.addObserver(obj2);
            ms.addObserver(obj3);
            
            ms.set("班长今晚请大家吃小龙虾");
            
            System.out.println(obj1.getMsg());
            System.out.println(obj2.getMsg());
            System.out.println(obj3.getMsg());
        }
    }

    类似群发信息给三个朋友(obj1,obj2,obj3),今晚一起吃小龙虾,他们同时收到消息。测试结果如下:

    班长今晚请吃小龙虾

    班长今晚请吃小龙虾
    班长今晚请吃小龙虾

    观察者模式总结:

    目标对象需要继承Observable,通过setChanged()和notifyObservers()通知观察者;

    观察者需要实现Observer接口,通过.addObserver(this)来注册成为观察者,依靠update(Observable o, Object arg)来获取目标对象传递的数据。

  • 相关阅读:
    linux read 系统调用剖析
    IO流程及优化
    分布式存储比较
    BTree,B-Tree,B+Tree,B*Tree的数据结构
    Spectrum Scale
    unixbench测试
    网络文件系统与 Linux
    协程的实现
    进程池和线程池
    django-spirt 论坛主题
  • 原文地址:https://www.cnblogs.com/zzjlxy-225223/p/11019398.html
Copyright © 2011-2022 走看看