一、概述
1、定义
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)
2、通用类图
3、基本介绍
- 观察者模式是对象之间一对多的一种模式,被依赖的对象是Subject,依赖的对象是Observer,Subject通知Observer变化,Subject为1,Observer为多。
二、通用源码
Subject被观察者:
定义被观察者必须实现的职责,能够动态的添加、删除观察者。即它的作用是管理观察者并通过观察者消息。
//抽象被观察者
public abstract class Subject {
//定义一个观察者数组
private Vector<Observer> obsVector=new Vector<>();
//增加一个观察者
public void addObserver(Observer observer){
this.obsVector.add(observer);
}
//删除一个观察者
public void delObserver(Observer observer){
this.obsVector.remove(observer);
}
//通知所有观察者
public void notifyObservers(){
for (Observer observer:this.obsVector){
observer.update();
}
}
}
//具体的被观察者
public class ConcreteSubject extends Subject {
//具体的业务
public void doSomething(){
//业务逻辑处理
//通知观察者
super.notifyObservers();
}
}
Observer观察者:
观察者接收到Subject通知的消息之后,进行update处理。
//抽象观察者
public interface Observer {
//更新方法
public void update();
}
//具体的观察者
public class ConcreteObserver implements Observer {
@Override
public void update() {
//接收到信息,进行处理
}
}
Client调用:
public class Client {
public static void main(String[] args){
//创建一个被观察者
Subject subject=new ConcreteSubject();
//创建观察者
Observer observer=new ConcreteObserver();
//添加观察者
subject.addObserver(observer);
//通知观察者消息变更
subject.notifyObservers();
}
}
三、观察者模式的应用
1、优点
- 观察者和被观察者是抽象耦合:这样设计对于观察者与被观察者的增加都非常容易扩展;
- 可以建立一套触发机制,将单一职责的类连起来形成一个触发链。简单的说,就是可以解决因为一个变化而引起的一连串的连锁反应。
2、缺点
- 观察者模式使用时需要考虑开发效率和运行效率的问题,一个被观察者,多个观察者,消息的通知是顺序进行的一个观察者卡壳,就会影响整体的执行效率。因此可以考虑异步的方式。
3、使用场景
- 关联行为场景,需要注意的是关联行为是可拆分的,而不是“组合”关系;
- 事件多级触发场景;
- 跨系统的消息交换场景,如消息队列的处理机制
四、Observable源码应用分析
1、类图分析
2、部分源码分析
Observer接口:
public interface Observer {
void update(Observable o, Object arg);
}
Observable类:
public class Observable {
private Vector<Observer> obs;
//添加观察者
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) {
/*
* 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)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
}