设计模式(二)java内置的观察者模式

  1. 概述
    java.util包内包含最基本的Observer接口和Observable类,这和上一节的Observer接口与Subject接口很相似。Observer接口和Observable类使用上更方便。因为许多功能已经事先准备好了,甚至可以使用推(push)或拉(pull)的方式传递数据。但是Observable类也有一些黑暗面,有时候我们还是需要实现自己的主题接口。
  2. UML
    这里写图片描述

    说明:
    java内置的观察者模式与上一节介绍的观察者区别在于

    1) Observable是一个类而不是一个接口,ConcreteSubject扩展了它并且继承了一系列增加、删除、通知等方法。Observable中添加了一个changed成员变量,和相关的setChanged()、clearChanged()、hasChanged()方法,用来标记状态的改变情况,当changed值为true时调用notifyObservers()方法才会更新观察者。(这样做是很有必要的,可以使设计更有弹性,我们可以在更适当的时候更新观察者)。

    2) Observable类虽然提供了有用的功能但是它的实现也存在许多问题,限制了它的使用和复用。首先Observable是一个类而不是一个接口,并且它没有实现一个接口,我们必须设计一个类去继承它,如果某类需要同时具有Observable和另一个超类的行为,就会陷入两难,毕竟java不支持多重继承,这限制了Observable的复用潜力。再者Observable中状态相关的关键操作(例如setChanged()方法)是protected的,这意味着除非继承自Observable,否则我们无法创建Observable实例并组合到自己的对象中来。这个设计违反了“多用组合,少用继承”的设计原则。

    3) Observer接口基本没有太大的改变,只是方法签名变了,如果想“推”数据给观察者,可以把数据当做数据对象传递给notifyObservers(arg)方法,否则观察者就必须从可观察者对象中“拉”数据(下面的实现是一个“拉”数据的例子)。

  3. 实现

/**
 * 下面的实现省略了包名和这两个import操作
 */
import java.util.Observable;
import java.util.Observer;
/**
 * 子类-具体的可观察者(主题)
 */
public class ConcreteSubject extends Observable {

    private String message;

    /**
     * 更新消息
     * 需要先调用setChanged()方法标记状态已经改变。
     * 使用“拉”的方式:这里调用notifyObservers()没有传递数据对象。
     */
    public void messageChanged() {
        setChanged();
        notifyObservers();
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
        messageChanged();
    }
}
/**
 * 接口实现类-具体的观察者
 */
public class ConcreteObserver implements Observer {

    /**
     * 这里保存对subject的引用,是因为如果以后要取消注册,
     * 已经有了对subject的引用会比较方便。
     */
    private Observable observable;

    public ConcreteObserver(Observable o) {
        this.observable = o;
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof ConcreteSubject) {
            ConcreteSubject ConcreteSubject = (ConcreteSubject) o;
            System.out.println(ConcreteSubject.getMessage());
        }
    }
}
/**
 * 测试类-观察者模式
 */
public class ObserverTest {
    public static void main(String[] args) {
        ConcreteSubject concreteSubject = new ConcreteSubject();
        Observer o1 = new ConcreteObserver(concreteSubject);
        Observer o2 = new ConcreteObserver(concreteSubject);
        Observer o3 = new ConcreteObserver(concreteSubject);
        concreteSubject.setMessage("Hello World !");
    }
}

运行结果:
这里写图片描述

参考资料:
《Head First设计模式》

猜你喜欢

转载自blog.csdn.net/ifwinds/article/details/69390270