设计模式之观察者模式

观察者模式(Observer),其含义是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式也称为发布-订阅模式。将一个系统分割一系列相互作用的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。 观察者模式的关键对象是目标和观察者,一个目标可以有任意数目的依赖它的观察者,一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的响应,灭个观察者都将查询目标以使其状态与目标的状态同步。目标是通知的发布者,它发出通知时并不需知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。

其适用性:

当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用,

当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变,

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

其结构图:

                 设计模式之观察者模式 

每个subject维护以个Observer的列表,意思是一个目标类可以被多个观察者观察,其可以绑定或解除一个observer;而observer类必须具有在subject改变时,接收到通知后更新相关信息(如状态)。实现如下:

 package org.designpattern.behavioral.observer;

import java.util.ArrayList;
import java.util.List;

public abstract class Subject {
    protected String state;
    protected List<Observer> observers;
    public abstract void attach(Observer observer);
    public abstract void detach(Observer observer);
    public abstract void notice();

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

  每个Subject的子类,在通知改变时会通知所有观察自己的观察者,具体代码可参考本博客的github。

在一个Observer抽象基类里,会有指定自己要观察的Subject实例,也就是具有该属性,通过记录它的状态来实现。下面是Observer的一个具体子类,其更新操作是记录目标的状态

package org.designpattern.behavioral.observer;

public class ConcreteObserverA extends Observer {
    public ConcreteObserverA(Subject subject){
        this.subject = subject;
        this.subject.attach(this);
    }
    @Override
    public void update(Subject subject) {
        //To change body of implemented methods use File | Settings | File Templates.
       this.setState(subject.getState());
    }

} 

  客户端测试类较为简单:

package org.designpattern.behavioral.observer;

public class Main {
    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();
        Observer obsvrA = new ConcreteObserverA(subject);
        Observer obsvrB = new ConcreteObserverB(subject);

        subject.setState("red");
        System.out.println(obsvrA.getState());
        System.out.println(obsvrB.getState());

        subject.notice();
        System.out.println(obsvrA.getState());
        System.out.println(obsvrB.getState());
    }

} 

  第一次观察者的state都是null,在获取subject通知后,再次获取state就是变成了red。

观察者模式在书中的例子是关于数据显示问题,这样根据需要做粗不同的显示图。观察者模式和协调者模式一样都是定义一对多的对象关系,此模式可使得对象之间进行同步通信。该模式可与单例模式一起构建一个更改管理其对象,经典的MVC思想非常类似观察者模式,只是观察的对象不同,其是视图页面来观察数据。