JDK自带的观察者模式和我们上一节说的基本相似,也有通用的观察协议规则 Observer,这个接口中只有一个方法,就是update方法
JDK也有一个可观察者 Observable类,如下
和我们写的有一点差异,jdk里面有个changed变量,而且每次通知时候都会去检测changed,只有当changed为true是才会去通知
这个说明了jdk在通知之前必须设置changed为true,才能进行通知,可是为什么要用这个呢,很多人都不明白,那就跟我一起来看看吧!其实这样设置是有好处的,让你在用观察者时更有弹性,你可以更适当的通知观察者。比方说,我们又一个温度监测站,当温度变化时,我们需要更新显示板上的显示,可是检测温度的硬件设备是非常灵敏的,但是我们的更新不需要做到那么的敏感,而且也不需要更新的那么频繁,所以我们就要在特定的条件下才能对温度的显示进行更新,这个就发挥出jdk中的setChanged的用处了,可以在特定的条件下去改变changed,这样温度通知才能发出,通知到每个注册者
接下来我们重新实现我们观察模式的实例,用jdk自带的类进行
由于要设置changed,而set方法是protected类型的,所以我们要重新封装这个类,并且要继承jdk自带的:
观察者:
展示接口:
基本的东西都写好了,我们写个测试类测试一下吧
这个测试类我们分别能看到我们在没有设置changed和设置changed是的结果
END
public interface Observer {
void update(Observable o, Object arg);
}
JDK也有一个可观察者 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();
}
}
和我们写的有一点差异,jdk里面有个changed变量,而且每次通知时候都会去检测changed,只有当changed为true是才会去通知
这个说明了jdk在通知之前必须设置changed为true,才能进行通知,可是为什么要用这个呢,很多人都不明白,那就跟我一起来看看吧!其实这样设置是有好处的,让你在用观察者时更有弹性,你可以更适当的通知观察者。比方说,我们又一个温度监测站,当温度变化时,我们需要更新显示板上的显示,可是检测温度的硬件设备是非常灵敏的,但是我们的更新不需要做到那么的敏感,而且也不需要更新的那么频繁,所以我们就要在特定的条件下才能对温度的显示进行更新,这个就发挥出jdk中的setChanged的用处了,可以在特定的条件下去改变changed,这样温度通知才能发出,通知到每个注册者
接下来我们重新实现我们观察模式的实例,用jdk自带的类进行
由于要设置changed,而set方法是protected类型的,所以我们要重新封装这个类,并且要继承jdk自带的:
观察者:
public class BossSubject extends Observable {
public void registerObserver(Observer observer) {
addObserver(observer);
}
public void removeObserver(Observer observer) {
removeObserver(observer);
System.out.println("成功告诉观察者我不需要被通知了");
}
public void setChanged() {
super.setChanged();
}
public void notifyAllObserver() {
System.out.println("开始通知");
notifyObservers();
System.out.println("所有的都已通知!");
}
}
展示接口:
public interface DisplayWork {
//收到通知后,打印一下自己正在干什么
void display();
}
注册对象必须实现jdk自带的OBserver接口,并在update里面进行相应的响应事件操作
public class Worker implements Observer, DisplayWork {
private String name;
private String des;
public Worker(String name, String des) {
super();
this.name = name;
this.des = des;
}
@Override
public void display() {
System.out.println("我在" + des + "了!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("老板来了," + name + "好好干活啦!");
this.display();
}
}
基本的东西都写好了,我们写个测试类测试一下吧
public class Test {
public static void main(String[] args) {
//首先定义一个观察者去观察
BossSubject sub = new BossSubject();
//定义张三,写代码
Worker zs = new Worker("张三", "写代码");
//告诉观察者,我需要知道老板什么时候来的
sub.registerObserver(zs);
//定义李四,管后勤
Worker ls = new Worker("李四", "管后勤");
//告诉观察者,我需要知道老板什么时候来的
sub.registerObserver(ls);
//定义王五,写代码
Worker ww = new Worker("王五", "秘书");
//告诉观察者,我需要知道老板什么时候来的
sub.registerObserver(ww);
//这时候,老板来了,告诉所有的人,老板来了
//这个没有设置changed
System.out.println("jdk changed not config");
sub.notifyObservers();
System.out.println("jdk changed config");
sub.setChanged();
sub.notifyAllObserver();
}
}
这个测试类我们分别能看到我们在没有设置changed和设置changed是的结果
jdk changed not config
jdk changed config
开始通知
老板来了,王五好好干活啦!
我在秘书了!
老板来了,李四好好干活啦!
我在管后勤了!
老板来了,张三好好干活啦!
我在写代码了!
所有的都已通知!
从结果中可以看出,当我们没有设置changed是进行通知是无效的,这就是jdk自带的观察者模式和我们自己写的观察者的区别之处了,jdk的观察者还是比较好,程序的弹性比较好。
好了,这节就说到这里了,请继续关注我们后续的设计模式讲解。END