观察者模式定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并被自动更新。
观察者模式使用场景
- 关联行为场景,需要注意的是,关联行为是可拆分的
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制
观察者模式的 UML 类图
观察者模式主要角色
- Subject:抽象主题,被观察者(Observable)的抽象,管理着众多观察者的实现,可以实现添加或删除观察者的功能。
- ConcreteSubject:具体主题,被观察者(Observable)的实现,通过该实现来向观察者发送通知。
- Observer:抽象观察者(Observer),观察者的抽象。一般是接口,实现该接口生成各种各样的观察者
- ConcreteObserver:具体观察者,抽象观察者的具体实现,当被观察者发生变化时执行具体逻辑。
观察者模式简单实现
//一个可在观察者要得到 observable 对象更改通知时可实现 Observer 接口的类。
public interface Observer {
//只要改变了 observable 对象就调用此方法。
void update(Observable o, Object arg);
}
//可将其子类化,表示应用程序想要观察的对象。
//一个 observable 对象可以有一个或多个观察者
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
/** 构造一个带有零个观察者的 Observable。 */
public Observable() {
obs = new Vector<>();
}
/**
* 如果观察者与集合中已有的观察者不同,则向对象的观察者集中添加此观察者。
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* 从对象的观察者集合中删除某个观察者。
* @param o the observer to be deleted.
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
* 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用
* clearChanged 方法来指示此对象不再改变。
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用
* clearChanged 方法来指示此对象不再改变。
*/
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
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();
}
/**
* 标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。
*/
protected synchronized void setChanged() {
changed = true;
}
/**
*指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以 hasChanged 方法将返回 false。
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* 测试对象是否改变。
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* 返回 Observable 对象的观察者数目。
*/
public synchronized int countObservers() {
return obs.size();
}
}
Observer 和 Observable 是 JDK 中的内置类型,这里 Observer 是抽象的观察者角色,Observable 对应的是被观察的对象。
实例:
import java.util.Observable;
import java.util.Observer;
//程序员是观察者
public class CoderObserver implements Observer {
private String name;
public CoderObserver(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + ": 有更新了 " + arg.toString());
}
}
import java.util.Observable;
//主体 被观察者
public class Subject extends Observable {
//业务方法,一旦执行某个操作,则通知观察者
public void postNewPublication(String content) {
//标识状态或者内容发送改变
setChanged();
//通知所有观察者
notifyObservers(content);
}
}
//测试类
public class Test {
public static void main(String[] args) {
//被观察者
Subject subject = new Subject();
//观察者
CoderObserver coder1 = new CoderObserver("code-1");
CoderObserver coder2 = new CoderObserver("code-2");
CoderObserver coder3 = new CoderObserver("code-3");
//将观察者注册到可观察对象的观察列表中
subject.addObserver(coder1);
subject.addObserver(coder2);
subject.addObserver(coder3);
//发布消息
subject.postNewPublication("新消息");
}
}
输出结果:
code-3: 有更新了 新消息
code-2: 有更新了 新消息
code-1: 有更新了 新消息
一个 observable 对象可以有一个或多个观察者。观察者可以是实现了 Observer 接口的任意对象。一个 observable 实例改变后,调用 Observable 的 notifyObservers 方法的应用程序会通过调用观察者的 update 方法来通知观察者该实例发生了改变。
未指定发送通知的顺序。Observable 类中所提供的默认实现将按照其注册的重要性顺序来通知 Observers,但是子类可能改变此顺序,从而使用非固定顺序在单独的线程上发送通知,或者也可能保证其子类遵从其所选择的顺序。
注意,此通知机制与线程无关,并且与 Object 类的 wait 和 notify 机制完全独立。
新创建一个 observable 对象时,其观察者集是空的。当且仅当 equals 方法为两个观察者返回 true 时,才认为它们是相同的。
网友评论