标签:
前言:
观察者(Observer)模式是对象的行为模式,又叫做发布-订阅模式、模型-视图模式、源-监听器模式或从属者模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化是,会让通知所有观察者对象,是他们能够自动更新自己。
(一)观察者模式的简略图:
(二)观察者模式的环境角色
抽象主题(Subject)角色:主题角色把所有对观察者对象的引用保存在一个聚集(比如Vector对象)里,每个主题都可以有任何数量的观察者。
抽象观察者者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知是更新自己。
具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
具体观察者(ConcreteObserver)角色:存储与主题的状态自已的状态。
(三)示例源码:
抽象主题(Subject)角色:
package com.observer;
public interface Subject
{
/**
* 调用这个方法登记一个新的观察者对象
* @param observer
*/
public void attach(Observer observer);
/**
* 调用这个方法删除一个已经登记过的观察者对象
* @param observer33
*/
public void detach(Observer observer);
/**
* 调用这个方法通知所有登记过的观察者对象
*/
void notifyObserver();
}
抽象观察者者(Observer)角色:
package com.observer;
public interface Observer
{
/**
* 调用这个会更新自己
*/
void update()
}
具体主题(ConcreteSubject)角色:
package com.observer;
import java.util.Enumeration;
import java.util.Vector;
public class ConcreteSubject implements Subject
{
private Vector observersVector=new Vector();
/**
* 调用这个方法登记一个新的观察者对象
*/
public void attach(Observer observer)
{
observersVector.addElement(observer);
}
/**
* 调用这个方法删除一个已经登记过的观察者对象
*/
public void detach(Observer observer)
{
observersVector.removeElement(observer);
}
/**
* 通知这个方法通知所有登记过的观察者对象
* @return
*/
public void notifyObserver()
{
Enumeration enumeration=observers();
while(enumeration.hasMoreElements())
{
((Observer)enumeration.nextElement()).update();
}
}
public Enumeration observers()
{
return((Vector)observersVector.clone()).elements();
}
}
具体观察者(ConcreteObserver)角色:
package com.observer;
public class ConcreteObserver implements Observer
{
/**
* 调用这个方法会更新自己
*/
public void update()
{
System.out.println("I am notified");
}
}
(四)JDK中的Observer
Observer接口
源码
抽象观察者者(Observer)角色:
package java.util;
public interface Observer
{
/**
*调用这个方法会更新自己
*/
void update(Observable o, Object arg);
}
java.util.Observable类
抽象主题类(被观察者)
package java.util;
public class Observable {
private boolean changed = false;
private Vector obs;
/** Construct an Observable with zero Observers. */
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);
}
/**
* 相当于notifyObserver(null)
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
*如果被对象有变化(那时hasChannged方法会返回true)
*调用本方法通知所有登记在案的观察者,调用它们的update()方法
*传入this和arg作为参量
*/
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();
}
}
每个观察者都是实现Observer接口的对象。在被观察者对象发生变化时,他会调用Observable的notifyObservers方法,此方法调用所有的具体观察者的update()方法,从而是所有的观察者都被通知更新自己。
调用例图如下:
(五)观察者模式的应用场景
1、对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
(六)观察者模式是的优缺点
优点
1)观察 者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。被观察者 并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
(2)观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。
观察者模式有下面的一些缺点:
(1) 如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
(2)如果在被观察者之间有循环依赖的话, 被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。
(3)如果对观察者的通知是通过另外的线程进 行异步投递的话,系统必须保证投递是以自恰的方式进行的。
(4)虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者 模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
参考资料《java与模式》
《head first 设计模式》
标签:
原文地址:http://blog.csdn.net/fujiaming123/article/details/51338726