观察者模式

  当对象间存在一对多关系时,则使用观察者模式(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);
        }
    }

 

posted @ 2021-05-19 20:48  纪煜楷  阅读(455)  评论(0编辑  收藏  举报