【导读】队列中有一种模式是发布/订阅模式,订阅者可以有多个,当发布者发布了消息的时候,订阅者会收到通知,这就是观察者模式,也可以理解为生产者/消费者。
一、定义
定义了对象之间一对多的依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化后,它的所有观察者都会收到通知并更新。
二、实例
比如微信的朋友圈,当有好友发了朋友圈动态之后你会收到一个通知,就是朋友圈入口的那个红点。
此时朋友圈是一个被观察者,你的账号是一个观察者。
Java提供了Observable(被观察者)和Observer(观察者),只需继承这两个类就可以实现观察者模式。
朋友圈动态:表明是谁发了什么内容的朋友圈
public class Trends {
private String userName;
private String content;
public Trends(String userName, String content) {
this.userName = userName;
this.content = content;
}
}
朋友圈对象:
public class FriendCircle extends Observable {
public void productTrends(Trends trends) {
System.out.println(trends.getUserName()+"发了一条朋友圈,内容是:"+trends.getContent());
1、这方法表明被观察者状态有更新
setChanged();
2、通知所有观察者
notifyObservers(trends);
}
}
微信账号:
public class WechatCount implements Observer{
1、账号昵称
private String userName;
public WechatCount(String userName) {
this.userName = userName;
}
2、收到通知后,会获取相应的内容进行逻辑处理
@Override
public void update(Observable o, Object arg) {
Trends trends = (Trends) arg;
System.out.println(this.userName+"接收到一条朋友圈动态更新通知,是"+trends.getUserName()+"发布的,内容是:"+trends.getContent());
System.out.println(this.userName+"评论说:你真TM恶心");
}
}
测试类:
public static void main(String[] args) {
1、定义一个朋友圈(被观察者)
FriendCircle friendCircle = new FriendCircle();
2、定义账号(观察者)
WechatCount wechatCount = new WechatCount("Liusy");
3、注册观察者
friendCircle.addObserver(wechatCount);
4、更新状态
friendCircle.productTrends(new Trends("张三","今天终于舔到女神了,我tm真优秀"));
}
结果:
类图:
源码解析:
(1)为什么观察者可以收到通知?
因为被观察者包含了一个观察者的集合。
观察者需要进行注册:
当被观察者调用setChanged方法的时候,改变的是charged这个属性值
protected synchronized void setChanged() {
changed = true;
}
然后会调用notifyObservers方法通知观察者
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
1、setCharged方法
if (!changed)
return;
arrLocal = obs.toArray();
2、将charged重置为false
clearChanged();
}
3、遍历观察者,调用其update方法
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
上述代码表明被观察者更新后为什么观察者会收到通知。