观察者模式是对象的行为模式,又叫发布-订阅模式、源-监听器模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能自动更新自己。
结构与角色
- 抽象主题角色:主题角色把对观察者对象的引用保存在一个集合中,抽象主题提供一个接口,可以增加和删除观察者对象。
- 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
- 具体主题角色:将有关联状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
- 具体观察者角色:存储与主题的状态相同的状态。
//抽象主题角色
public interface Subject{
void attach(Observer o);
void detach(Observer o);
void notifyObservers();
}
//具体主题角色
public class ConcreteSubject implements Subject{
private List<Observer> observers = new ArrayList<Observer>;
public void attach(Observer o){
observers.add(o);
}
public void detach(Observer o){
observers.remove(o);
}
public void notifyObservers(){
for(Observer o:obervers){
o.update();
}
}
}
//抽象观察者角色
public interface Observer{
void update();
}
//具体观察者角色
public class ConcreteObserver implements Observer{
public void update(){
System.out.print("change");
}
}
Java对于观察者模式的支持
Java的util库中,提供了一个Observable类和Observer接口,构成对观察者的支持。
Observer接口:抽象观察者角色,定义update方法,当被观察者对象的状态变化时,被观察者对象的notifyObservers调用这一方法。
package java.util;
/**
* A class can implement the <code>Observer</code> interface when it
* wants to be informed of changes in observable objects.
*
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}
Observable类:相当于抽象主题角色。被观察者类都是Observable类的子类。有两个方法很重要:setChanged()被调用后会设置一个内部标记变量,代表状态发生了变化,另一个是notifyObservers(),通知观察者更新自己。
Java中的DEM事件机制
DEM:委派事件模型(Delegation Event Model),主题角色发布事件,而观察者角色向特定的主题订阅它感兴趣的事件。当一个具体主题产生一个事件时,它会通知感兴趣的订阅者。发布者叫做事件源,而订阅者叫做事件监听器。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。