Java 理解观察者模式
2019-08-01 本文已影响19人
殷天文
前言:最近在学习RxJava,RxJava在观察者模式的基础上做了扩展,本文带大家了解观察者模式
什么是观察者模式
观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
当对象间存在一对多关系时,适合使用观察者模式。当一个对象被修改时,会自动通知它的依赖对象。观察者模式属于行为型模式。
例如:订单支付成功后,可能会减商品库存,计算会员积分,通知物流发货等等。
观察者模式中的一些概念
- Observable 被观察者
- Observer 观察者
将刚刚的例子抽象为观察者模式的话,应该是这样的
image.pngJava API
Java 为我们提供了Observable 和 Observer 两个API,可以用来拓展实现观察者模式
观察者接口很简单,当 被观察者发生改变时,会通过update方法通知所有的 观察者
public interface Observer {
void update(Observable o, Object arg);
}
被观察者代码,稍微多了一些,但是也并不复杂。JDK为我们提供了一个线程安全的被观察者模型
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();
}
}
实现
小栗子:公众号发布文章时,推送给所有订阅的用户
/**
* 公众号
* (被观察者)
*/
class OfficialAccount extends Observable {
// 发布文章
public void publishArticle(String article) {
setChanged();
notifyObservers(article);
}
}
/**
* 用户
* (观察者)
*/
class User implements Observer {
private String username;
User(String username) {
this.username = username;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("用户:" + username + ", 收到订阅文章:" + arg);
}
}
public class Run {
public static void main(String[] args) {
OfficialAccount officialAccount = new OfficialAccount();
User ytw = new User("ytw");
User hmj = new User("hmj");
officialAccount.addObserver(ytw);
officialAccount.addObserver(hmj);
officialAccount.publishArticle("SpringBoot");
officialAccount.publishArticle("Java 理解观察者模式");
}
}
一点理解
在学习观察者模式的时候,总感觉和生产者消费者很像,两者都很好的做到了解耦。上述的观察者模型,如果订阅者很多的话,处理起来效率是很差的(因为是同步的)。个人理解生产者消费者模式属于观察者模式的变种。生产者消费者模式添加了缓冲队列,可以很好的做到异步消息吞吐。