概念
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
观察者模式主要有两个角色
- Subject 观察主题对象,也可以叫被观察或者被订阅对象
- Observer 观察者或者订阅者对象,当
Subject
有变动,就会通知到每一个Observer
我们按照定牛奶的方式来理解,Subject
实际上可以理解成奶厂,Observer
可以理解成为我们每个用户,而观察者模式就是在Subject
发生变化的时候,去通知每一个Observer
对象,以达到消息通知目的。
这是从别人博客中直接拿的图(https://blog.csdn.net/chengyuqiang/article/details/79222294)
自己实现一个观察者模式
定义观察者主题对象
/**
* 观察者主题对象
*/
public interface Subject {
/**
* 订阅操作
*/
void attach(Observer observer);
/**
* 取消订阅操作
*/
void detach(Observer observer);
/**
* 通知变动
*/
void notifyChanged();
}
定义观察者观察人对象
/**
* 观察者订阅人对象
*/
public interface Observer {
/**
* 接收变动通知
*/
void update();
}
分别创建Subject
和Observer
对象的实现类
public static class RealSubject implements Subject {
private List<Observer> observerList = new ArrayList<>();
@Override
public void attach(Observer observer) {
observerList.add(observer);
}
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyChanged() {
for (Observer observer : observerList) {
observer.update();
}
}
}
public static class RealObject implements Observer {
@Override
public void update() {
System.out.println("接收到了通知");
}
}
Observer
的实现可以是很多个,可以理解为平时一家奶厂,订奶用户肯定是有很多个。
调用实现
public static void main(String[] args) {
Subject subject = new RealSubject();
Observer observer = new RealObject();
subject.attach(observer);
subject.notifyChanged();
}
使用Java自带的观察者模式类实现
上面自己通过接口的方式,实现了一个观察者模式,但是Java自身也是有这方面的实现了,下面看看如何用Java自带的实现一个观察者模式
public static class RealSubject extends Observable {
public void makeChanged() {
setChanged();
notifyObservers();
}
}
public static class RealObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("调用了-->");
}
}
public static void main(String[] args) {
RealSubject subject = new RealSubject();
RealObserver observer = new RealObserver();
subject.addObserver(observer);
subject.makeChanged();
}
调用的基本逻辑是一样的。Java已经帮我们把订阅和取消订阅操作都封装了起来,通知也进行了封装,并且进行了同步处理。只要需要注意的是,这里有个setChanged();
,在发生变化之后,必须调用这个方法告诉发生了改变,否则不会正常处理消息的。
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) //这里的标志位就是setChanged处理的标志位
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
好了,观察者模式就到这里了。