GoF说道:Observer模式的意图是“定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”。
1, 观察者(具体执行操作的对象,有多个)
2, 被观察者(顾名思义是被观察的对象,如果该对象发生某些变化则通知观察者执行对应的操)
在 JDK的util包中有 Observable 类和 Observer 接口,被观察者继承 Observable 类,观察者实现 Observer 接口就可实现观察者模式。
举一个简单例子,假如我是卖杂志的老板,有很我顾客订购杂志,如果每位顾客总是询问订购的杂志是否到了,那要回答这些问题相当麻烦,如果我和每位顾客商量好,你订购的杂志一到,我就发消息通知,这样就没有人总打电话来骚扰了。
每位顾客就是观察者,顾客订购的杂志就是被观察者。
Java 提供了 Observer 模式的默认实现,下面我们就看一下 Java 对 观察者模式的支持
- public class Observable {
- private boolean changed = false;
- private Vector obs;
- //创建被观察者时就创建一个它持有的观察者列表,注意,这个列表是需要同步的。
- 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);
- }
- /**
- * 通知操作,即被观察者发生变化,通知对应的观察者进行事先设定的操作,不传参数的通知方法
- */
- public void notifyObservers() {
- notifyObservers(null);
- }
- /**
- * 与上面的那个通知方法不同的是,这个方法接受一个参数,这个参数一直传到观察者里,以供观察者使用
- */
- 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);
- }
- }
- 其它方法省略。。。。。
Observer 接口如下:
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
* @version 1.19, 12/19/03
* @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);
}
下面写自己的业务类:
//被观察者
public class Magazine extends Observable{
private String name; //杂志名称
public Magazine(String name){
this.name=name; //构造方法,其它属性继续添加
}
public String getName(){
return this.name;
}
//发送消息
public void setMessage(String name){
/*
* 注意 :在通知 所有观察者之前
* 一定要调用 setChanged()方法来设置被观察者的状态已经被改变,
*/
this.setChanged();
//通知所有观察者
this.notifyObservers(name);
}
}
//观察者
public class Customer implements Observer{
private String name;
public Customer(String name) {
this.name = name;
}
public void update(Observable observable,Object arg){
System.out.println(this.name + "你订阅的" + ((Magazine)observable).getName() + arg);
}
}
public class Client {
public static void main(String[] args){
//添加三个顾客
Customer toyne = new Customer("toyne");
Customer nikey = new Customer("nikey");
Customer mike = new Customer("mike");
Magazine maz= new Magazine("鲁迅散文集");
maz.addObserver(toyne);
maz.addObserver(nikey);
maz.addObserver(mike);
//向订鲁迅散文集 的顾客发送消息
maz.setMessage("已经到了!");
}
}
//output
mike你订阅的鲁迅散文集已经到了!
nikey你订阅的鲁迅散文集已经到了!
toyne你订阅的鲁迅散文集已经到了!
观察者模式(Observer)完美的将观察者与被观察者的对象分离开。观察者模式有很多中实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。实现观察者模式的时候要注意,观察者与被观察者对象之间的互动关系不能体现成类之间的直接调用。否则就将使观察者与被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。无论是观察者‘观察’观察对象,还
是被观察者将自己的改变‘通知’观察者,都不应该直接调用。