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