上篇咱们讲解了观察者模式的一些知识,并且自定义观察者模式的经典代码,(传送们:设计模式走一遍—-观察者模式(上))设计模式
这篇简单讲一下JDK自带的观察者模式实现代码。安全
对于观察者模式,JDK中提供了一个Observer接口(观察者),一个Observable类(主题对象)。markdown
注:被观察者又被称为主题对象,目标对象。app
具体咱们来看下源码。ide
1.观察者接口测试
public interface Observer { /** * This method is called whenever the observed *object is changed. *当被观察者发生变化时,该方法将会被调用 * @param o the observable object. * @param arg an argument passed to the <code>notifyObservers</code> * method. */ void update(Observable o, Object arg); }
该接口至关于观察者,里面有一个update(Observable o, Object arg)方法,Observable参数是指主题对象,该参数指明该观察者是属于哪个主题对象的。this
arg参数能够是任意对象,假如主题对象在发送通知时,想要传递什么数据给观察者,那么就能够把数据对象传递给arg参数。线程
2.主题对象类(方法有点多,我就不放英文解释了)设计
//主题对象能够是接口、抽象类、具体类,咱们上节说 //通常采用抽象类,不过JDK这里使用的是具体类 public class Observable { //标记主题对象的状态是否改变 private boolean changed = false; //存放观察者集合,之因此用Vector而不用ArrayList //主要是Vector是线程安全的 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); } //标记该对象的状态是否发送了改变 protected synchronized void setChanged() { changed = true; } //指示该对象不会再发生改变,或者它已经通知了 //全部观察者 protected synchronized void clearChanged() { changed = false; } //测试对象是否发生了改变。当且仅当在此对象最近 //调用了setChange()方法 public synchronized boolean hasChanged() { return changed; } //若是hasChanged()方法指示此对象发送了改变, //则通知全部观察者,而且调用clearChanged()方法 //指示此对象再也不改变 public void notifyObservers() { notifyObservers(null); } //与上面没有参数的同名方法相同,只是若是这个方 //法的arg参数能够接受主题对象想要传递观察者的数据对象 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(); } //返回观察者的数量 public synchronized int countObservers() { return obs.size(); } }
该具体类Observable至关于主题对象,实现的主要功能就是当本身的状态发送改变时,通知观察者,观察者再根据通知,在update方法作出相应的反应。code
简单写个Demo测试下。
public class Test { public static void main(String[] args){ //建立一个主题对象 AnimalSubject animalSubject = new AnimalSubject(); animalSubject.addObserver(new DogObsever()); animalSubject.addObserver(new LionObsever()); //状态发生改变 animalSubject.setChanged(); //通知观察者 animalSubject.notifyObservers(); } } //动物主题,弄子类方便拓展主题对象功能 class AnimalSubject extends Observable{ //不过我就不新增代码、方法了 //不覆盖下的话,上面的测试调用不了setChange()方法 //为了方便测试,覆盖重写下 @Override protected synchronized void setChanged() { super.setChanged(); } } class DogObsever implements Observer{ @Override public void update(Observable o, Object arg) { System.out.println("收到通知,小狗观察者正在作出相应处理"); } } class LionObsever implements Observer{ @Override public void update(Observable o, Object arg) { System.out.println("收到通知,狮子观察者正在作出相应处理"); } }
打印结果
收到通知,狮子观察者正在作出相应处理 收到通知,小狗观察者正在作出相应处理
从上面的代码中咱们能够发现JDk内置的观察者模式中的主题对象是一个具体类,而不是一个抽象类或接口,并且setChange()方法还被保护起来了(被定义为protected),这就意味着,要在别的类中调用该方法,那么咱们必须继承在子类中重写覆盖该方法。显然,我以为这很不友好…..
可能这也是JDK内置的观察者模式不多被拿来使用 的缘由吧,通常都是本身来自定义观察者模式。
但愿你们可以动手写一下这些代码,可能会碰到一些你没想到的问题。
完
关注公个人众号:苦逼的码农,获取更多原创文章,后台回复礼包送你一份时下热门的资源大礼包。同时也感谢把文章介绍给更多须要的人