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

      当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式

      场景:学生1和2观察等待着老师布置作业,老师通过微信布置完作业,学生1和2便同时接收到了通知,但学生1决定再看会电视,学生2决定马上写作业

      在该场景中,老师为被观察的对象,当该对象发生了变化(布置作业),则自动通知到了依赖他的学生1和2,然后1和2根据通知做出不同的响应

      

      被观察的老师实现类:做法是继承Observable类,触发动作后调用父类的setChanged(对象变化)和notifyObservers(通知依赖他的对象)   ——文末有Observable源码解析

    import java.util.Observable;
    
    /**
     * 老师布置的作业及时通知到stu1和stu2
     * stu1和stu2通过观察模式实现老师布置作业后的动作
     * @author test11
     */
    public class Teacher extends Observable {
    
        /**
         * 布置作业
         */
        public void giveWork(){
            String work = "默写课文一遍";
            System.out.println("开始布置作业");
            super.setChanged();
            super.notifyObservers(work);
        }
    
    }

      观察老师的两个对象学生1和2,实现Observer接口,在update方法中去更新自己的后续操作

    import java.util.Observable;
    import java.util.Observer;
    
    /**
     * 学生通过监听老师布置作业的动作,完成后续动作
     * @author test11
     */
    public class Stu1 implements Observer {
    
        @Override
        public void update(Observable o, Object arg) {
            System.out.println("老师布置作业了," + arg.toString());
            System.out.println("stu1决定再看会电视");
        }
    }
    import java.util.Observable;
    import java.util.Observer;
    
    /**
     * 学生通过监听老师布置作业的动作,完成后续动作
     * @author test11
     */
    public class Stu2 implements Observer {
    
        @Override
        public void update(Observable o, Object arg) {
            System.out.println("老师布置作业了," + arg.toString());
            System.out.println("stu2决定马上写作业");
        }
    }

      老师做出动作,并通知他依赖的对象立即做出响应:

    import java.util.Observable;
    
    /**
     * 老师布置的作业及时通知到stu1和stu2
     * stu1和stu2通过观察模式实现老师布置作业后的动作
     * @author test11
     */
    public class Teacher extends Observable {
    
        /**
         * 布置作业
         */
        public void giveWork(){
            String work = "默写课文一遍";
            System.out.println("开始布置作业");
            super.setChanged();
            super.notifyObservers(work);
        }
    
    }

      父类Observable源码解析

    //被观察的对象变化后调用setChanged修改自己的状态,之后通知所有观察者,见notifyObservers方法
    protected synchronized void setChanged() {
            changed = true;
        }
    
    //通知方法首先判断状态是否已改变,状态改变是先决条件,状态改变则获取所有的观察者(见addObserver方法),循环调用观察者的update方法,达到通知的效果
    public void notifyObservers(Object arg) {
            /*
             * a temporary array buffer, used as a snapshot of the state of
             * current Observers.
             */
            Object[] arrLocal;
    
            synchronized (this) {
                /* We don't want the Observer doing callbacks into
                 * arbitrary code while holding its own Monitor.
                 * The code where we extract each Observable from
                 * the Vector and store the state of the Observer
                 * needs synchronization, but notifying observers
                 * does not (should not).  The worst result of any
                 * potential race-condition here is that:
                 * 1) a newly-added Observer will miss a
                 *   notification in progress
                 * 2) a recently unregistered Observer will be
                 *   wrongly notified when it doesn't care
                 */
                if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
    
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        }
    
    //被观察对象实例化时,需要添加观察者,观察者都是实现自Observer接口,在update方法里执行触发操作,添加的观察者放到obs数组对象里,该对象是全局变量,可供被观察对象通知观察者时获取所有对象实例
    public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
            if (!obs.contains(o)) {
                obs.addElement(o);
            }
        }
  • 相关阅读:
    LeetCode——Merge Two Sorted Lists
    【iOS与EV3混合机器人编程系列之四】iOS_WiFi_EV3_Library 剖析之中的一个:WiFi UDP和TCP
    Java 中最常见的 5 个错误
    Linux 设备驱动的固件载入
    kettle的job中使用循环
    Servlet 容器对URI的处理
    友元函数友元类.
    【批量加入】-拼接sql字符串
    java JSONObject/JSONArray详解
    java 中文转化为拼音
  • 原文地址:https://www.cnblogs.com/jiyukai/p/14786534.html
Copyright © 2011-2022 走看看