观察者模式的结构
观察者(Observer)模式是对象的行为型模式,又叫做发表-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-收听者(Source/Listener)模式或从属者(Dependents)模式。本模式的类图结构如下:
图1 观察者模式的静态结构
|
从类图中看清楚在观察者模式里有如下的角色:
. 抽象主题(Subject)角色:主题角色把所有的观察者对象的引用保存在一个列表里;每个主题都可以有任何数量的观察者。主题提供一个接口可以加上或撤销观察者对象;主题角色又叫做抽象被观察者(Observable)角色;
图2、抽象主题角色,有时又叫做抽象被观察者角色,可以用一个抽象类或者一个接口实现;在具体的情况下 也不排除使用具体类实现。 |
![]() 图3、抽象观察者角色,可以用一个抽象类或者一个接口实现;在具体的情况下也不排除使用具体类实现。 |
. 具体主题(ConcreteSubject)角色:保存对具体观察者对象有用的内部状态;在这种内部状态改变时给其观察者发出一个通知;具体主题角色又叫作具体被观察者角色;
![]() 图4、具体主题角色,通常用一个具体子类实现。 |
.具体观察者(ConcreteObserver)角色:保存一个指向具体主题对象的引用;和一个与主题的状态相符的状态。具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与主题的状态自恰。
![]() 图5、具体观察者角色,通常用一个具体子类实现。 |
下面给出一个示意性实现的Java代码。首先在这个示意性的实现里,用一个Java接口实现抽象主题角色,这就是下面的Subject接口:
|
代码清单1、Subject接口的源代码
public interface Subject
{
public void attach(Observer observer);
public void detach(Observer observer);
void notifyObservers();
}
|
|
代码清单2、ConcreteSubject类的源代码。
import java.util.Vector;
import java.util.Enumeration;
public class ConcreteSubject implements Subject
{
public void attach(Observer observer)
{
observersVector.addElement(observer);
}
public void detach(Observer observer)
{
observersVector.removeElement(observer);
}
public void notifyObservers()
{
Enumeration enumeration = observers();
while (enumeration.hasMoreElements())
{
((Observer)enumeration.nextElement()).update();
}
}
public Enumeration observers()
{
return ((Vector) observersVector.clone()).elements();
}
private Vector observersVector = new java.util.Vector();
} |
| 代码清单3、Observer接口的源代码 public interface Observer
{
void update();
}
|
| 代码清单4、ConcreteObserver类的源代码 public class ConcreteObserver implements Observer
{
public void update()
{
// Write your code here
}
}
|
![]() 图6、java.util提供的Observer接口的类图。 |
|
代码清单5、java.util.Observer接口的源代码
package java.util;
public interface Observer
{
/**
* 当被观察的对象发生变化时,这个方法会被调用。
*/
void update(Observable o, Object arg);
}
|
![]() 图7、Java语言提供的被观察者的类图。 |
![]() package java.util;
public class Observable
{
private boolean changed = false;
private Vector obs;
/** 用0个观察者构造一个被观察者。**/
public Observable()
{
obs = new Vector();
}
/**
* 将一个观察者加到观察者列表上面。
*/
public synchronized void addObserver(Observer o)
{
if (!obs.contains(o))
{
obs.addElement(o);
}
}
/**
* 将一个观察者对象从观察者列表上删除。
*/
public synchronized void deleteObserver(Observer o)
{
obs.removeElement(o);
}
/**
* 相当于 notifyObservers(null)
*/
public void notifyObservers()
{
notifyObservers(null);
}
/**
* 如果本对象有变化(那时hasChanged 方法会返回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();
}
/**
* 将“已变化”设为true
*/
protected synchronized void setChanged()
{
changed = true;
}
/**
* 将“已变化”重置为false
*/
protected synchronized void clearChanged()
{
changed = false;
}
/**
* 探测本对象是否已变化
*/
public synchronized boolean hasChanged()
{
return changed;
}
/**
* 返还被观察对象(即此对象)的观察者总数。
*/
public synchronized int countObservers()
{
return obs.size();
}
}
|
![]() 图8、使用Java语言提供的对观察者模式的支持。 |
![]() 图9、一个使用Observer接口和Observable类的例子。 |
代码清单6、Tester类的源代码
package com.javapatterns.observer.watching;
import java.util.Observer;
public class Tester
{
static private Watched watched;
static private Observer watcher;
public static void main(String[] args)
{
watched = new Watched();
watcher = new Watcher(watched);
watched.changeData("In C, we create bugs.");
watched.changeData("In Java, we inherit bugs.");
watched.changeData("In Java, we inherit bugs.");
watched.changeData("In Visual Basic, we visualize bugs.");
}
}
|
代码清单7、Watched类的源代码
package com.javapatterns.observer.watching;
import java.util.Observable;
public class Watched extends Observable
{
private String data = "";
public String retrieveData()
{
return data;
}
public void changeData(String data)
{
if ( !this.data.equals( data) )
{
this.data = data;
setChanged();
}
notifyObservers();
}
}
|
代码清单8、Watcher类的源代码
package com.javapatterns.observer.watching;
import java.util.Observable;
import java.util.Observer;
public class Watcher implements Observer
{
public Watcher(Watched w)
{
w.addObserver(this);
}
public void update( Observable ob, Object arg)
{
System.out.println("Data has been changed to: '" + ((Watched)ob).retrieveData() + "'");
}
}
|
|
代码清单9、被观察者的内部状态发生了改变
watched.changeData("In C, we create bugs.");
watched.changeData("In Java, we inherit bugs.");
watched.changeData("In Java, we inherit bugs.");
watched.changeData("In Visual Basic, we visualize bugs.");
|
代码清单10、运行的结果
Data has been changed to: 'In C, we create bugs.'
Data has been changed to: 'In Java, we inherit bugs.'
Data has been changed to: 'In Visual Basic, we visualize bugs.'
|
![]() 图10、菩萨和菩萨的守瓶乌龟。 |
![]() 图11、系统的类图。 |
观察者模式在jdk中体现
在图形化设计的软件中,为了实现视图和事件处理的分离,大多采用了观察者模式,java中的spring就采用了观察者模式,在现实的应用系统中也有很多的应用,比如当当网、京东商城一类的
电子商务网站,如果你对某件商品比较关注,可以放到收藏架中,那么商品降价时,系统给你发送短信或邮件,这就是观察者模式的一个典型应用,商品是被观察者也叫主体,关注该商品的客户就是观察者。
观察者模式在spring中的体现:
Spring中Observer模式常用的地方是listener的实现。如ApplicationListener
本文转自:http://www.blogjava.net/supercrsky/articles/202544.html











}
}



1874

被折叠的 条评论
为什么被折叠?



