问题提出:

 

在生活实际中,经常会遇到多种对象关注一个对象数据变化的情况。例如,生活中有温度记录仪,当温度发生变化时,需要完成如下功能:记录温度日志,显示温度变化曲线,当温度越界时扬声器发出声音。可能写出以下程序段。

While(温度变化){

  记录温度日志;

  显示温度变化曲线;

  当温度越界时扬声器发出声音;

}

这种方法把所有功能集成字一起,但是当需求发生变化,例如新增新的温度监测功能或者要删除某种功能,程序都得修改,这就是我们不希望看到的结果。观察者设计模式则是解决这类问题的有效办法。

观察者模式设计两种角色:主题和观察者。在上面的例子中,温度无疑就是主题,而记录温度日志,显示温度变化曲线,当温度越界时扬声器发出声音 即是三个观察者。观察者需要时刻“关注”主题的变化而作出不同的工作,就好像程序员都要围绕着开发需求一样编写代码,需求一改,我们需要立马改代码!明白了这两种角色之后,下面来仔细看看这两者之间的关系需要有什么功能。

开发需求是经理定的,对于经理来说,他需要知道有哪几个程序员为它工作,并且它根据需求可以新增或者剔除为它工作的程序员。那由此可以得出下面几个重要结论。

1)主题要知道有哪些观察者对其进行监测,所以主题类里面需要有集合类成员集合。

2)既然包含观察者对象集合,那么观察者必须是多态的,这就要求有共同的接口。

3)主题应该有的功能:添加观察者,撤销观察者,并向观察者发送消息,特别是“推数据”(下文会讨论)的模式。这三个功能固定,主题类可以从固定接口派生。

根据以上编写观察者设计模式,需要完成以下功能类。

1.主题ISubject接口定义

2.主题类编写

3.观察者接口IObserve定义

4.观察者类实现

UML图如下

Java设计模式:观察者模式

关键代码如下

1)观察者接口IObserver

public interface IObserver {
    //观察者接口
    public void refresh(String data);
}

2)主题接口ISubject

public interface ISubject{
    public void register(IObserver obs);            //注册观察者
    public void unregister(IObserver obs);          //撤销观察者
    public void notifyObservers();                  //通知所有观察者
}

3)主题实现类Subject

public class Subject implements ISubject {
    private Vector<IObserver> vec = new Vector<IObserver>();
    private String data;
    public String getData(){
        return data;
    }
    public void setData(String data){
        this.data = data;
    }
    public void register(IObserver obs){            //主题添加观察者
        vec.add(obs);
    }
    public void unregister(IObserver obs){          //主题撤销观察者
        vec.remove(obs);
    }
    public void notifyObservers(){                  //主题通知所有观察者进行数据响应
        for(int i=0;i<vec.size();i++){
            IObserver obs = vec.get(i);
            obs.refresh(data);
        }
    }
}

4)具体观察者Observer

public class Observer implements IObserver {
    public void refresh(String data){
        System.out.println("I have received the data:" + data);
    }
}

5)测试类Test

public class Test {
    public static void main(String[] args) {
        IObserver obs = new Observer();
        Subject subject = new Subject();
        subject.register(obs);
        subject.setData("Hello World!");
        subject.notifyObservers();
    }
}

View Code