概述

观察者定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者,使得他们能够自动更新自己。

结构图

可以看到,图中的被观察者也就是通知者,是一个抽象的类或者接口。然后下面实现它的类才是真正的通知者。右边的观察者也是一个抽象,其实现类才是真正被通知的对象。

同时,通知者应该具有添加和移除观察者的方法,通知事件的方法。观察者接口具有更新状态的方法。

代码示例

package com.ans;
import java.util.*;
interface Subject {
    public abstract void Attach(Observer obs);
    public abstract void Detach(Observer obs);
    public abstract void Notify(); 
}

class Monitor implements Subject {
    private String state;
    public String getState() {
        return this.state;
    }

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

    List<Observer> list = new ArrayList<Observer>();
    public void Attach(Observer obs) {
        list.add(obs);
    }

    public void Detach(Observer obs) {
        list.remove(obs);
    }

    public void Notify() {
        for(Observer obs : list) {
            obs.update(state);
        }
    }
}


abstract class Observer {
    public abstract void update(String newState);
}

class Student extends Observer {

    private String name;
    public Student(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
    @Override
    public void update(String newState) {
        if(newState.equals("come"))
            System.out.println(name + ":老师回来了,赶紧复习");
        else if(newState.equals("go"))
            System.out.println(name + ":老师走了,起来嗨");
    }
}

public class ObserverTest {
    public static void main(String[] args) {
        Monitor mo = new Monitor();
        Observer stu1 = new Student("小明");
        Observer stu2 = new Student("小红");

        mo.Attach(stu1);//添加小明
        mo.Attach(stu2);//添加小红

        mo.setState("come");
        mo.Notify();

        System.out.println("============================");
        mo.setState("go");
        mo.Notify();

        System.out.println("============================");
        mo.Detach(stu1);//以后不通知小明

        mo.setState("come");
        mo.Notify();
        System.out.println("============================");

        mo.setState("go");
        mo.Notify();

    }

}

运行结果:

小明:老师回来了,赶紧复习
小红:老师回来了,赶紧复习
============================
小明:老师走了,起来嗨
小红:老师走了,起来嗨
============================
小红:老师回来了,赶紧复习
============================
小红:老师走了,起来嗨

优缺点

观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。

观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。

但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。

总结

java语言中,有一个接口Observer,以及它的实现类Observable,对观察者角色常进行了实现。我们可以在jdk的api文档具体查看这两个类的使用方法。

做过VC++、javascript DOM或者AWT开发的朋友都对它们的事件处理感到神奇,了解了观察者模式,就对事件处理机制的原理有了一定的了解了。如果要设计一个事件触发处理机制的功能,使用观察者模式是一个不错的选择,AWT中的事件处理DEM(委派事件模型Delegation Event Model)就是使用观察者模式实现的。