JDK中的设计方式之观察者模式

JDK中的设计模式之观察者模式

今天我们来学习下JDK中实现观察者模式的接口和类.

在观察者模式中,有观察者和被观察者两种角色。(有些也称为发布者和订阅者角色等。。)

观察者可以通过注册方式加入到被观察者之内(通常用一个容器实现),

当某种变化发生时,被观察者可以通知所有加入到该容器的观察者。

GOF是这样定义观察者模式(Observer pattern):

Define a one-to-many dependency between objects so that 
when oneobject changes state, all its dependents are notified and updatedautomatically.

该模式类图如下:

JDK中的设计方式之观察者模式

好,下面进入主题。

在java.util包中有两个文件,一个是接口Observer.java,另外一个是Observable.java实现类.

看下源代码:

Observer.java:

package java.util;


public interface Observer {

    void update(Observable o, Object arg);
}

我们可以看到该接口只含有update()方法,该方法含有两个参数,第一个参数代表被观察者,第二个参数是为了将数据从被观察者发送到观察者(可以是任何类型)


在看看Observable.java实现类:

package java.util;

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);
    }

    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();
    }
}

注意到该类是用Vector向量来封装观察者,同时还增加了一个布尔字段changed,用来判断变化是否发生。

在该类中,含有几个核心方法,分别用来增加,删除和通知观察者,并且该类除了构造方法之外,其余都是同步的。

addObserver()
deleteObserver()
notifyObservers()


下面给出一个简单的书店进书通知所有注册顾客的例子:

首先实现Observer.java类:

package zjut.tsw.jdk.observer;

import java.util.Observable;
import java.util.Observer;

public class ClientObserver implements Observer{

	private String name;
	public ClientObserver(String name,Observable subject) {
		this.name = name;
		subject.addObserver(this);
	}
	@Override
	public void update(Observable o, Object arg) {
		System.out.println("您好," +name + "来自书店的消息:" + (String)arg);
	}

}

再继承类Observable.java:

package zjut.tsw.jdk.observer;

import java.util.Observable;

public class BookStore extends Observable{

	public void enableChange() {
		this.setChanged();
	}
}

最后再贴个通知类:


package zjut.tsw.jdk.observer;

public class BookNotification {

	public static void main(String args[]) {
		
		BookStore bookstore = new BookStore(); //创建被观察者-书店
		
		/*
		 * 创建观察者-顾客,并注册
		 */
		ClientObserver client1 = new ClientObserver("张三",bookstore);
		ClientObserver client2 = new ClientObserver("小红",bookstore);
		ClientObserver client3 = new ClientObserver("李四",bookstore);

		/*
		 * 有新书到了!
		 */
		bookstore.enableChange();
		bookstore.notifyObservers("三国演义");
		
		bookstore.notifyObservers("红楼梦");
	}
}

结果输出为:

您好,李四来自书店的消息:三国演义
您好,小红来自书店的消息:三国演义
您好,张三来自书店的消息:三国演义

细心的同学注意到书店进了三国演义和红楼梦,为什么输出中没有向客户通知红楼梦到了呢?

这个留给读者思考下。。。

^ ^

Over...