[原]设计模式之观察者模式

杨博东 16/11/30 16:28:43

一:观察者模式

定义一对多(1:n)的对象关系,如果1发生变化,那么n都会收到通知,这叫观察者模式。当然,我觉得叫”出版者——订阅者”模式更加容易理解。就像你在报社订了报纸,只要报社有新报纸出版,送报员就会给你家送一份,如果不想要,还可以退定。

二:来个栗子

举一个Head First书上的栗子:
这里写图片描述

首先这是一个气象局的显示系统,WeatherData是数据的来源,Subject是一个公共基础主题,Observer是观察者的父类。WeatherData的数据如果更新,我希望forecastObserver这个面板上的数据也更新,为了使结构简单,我没有添加xObserveryObserver等其他的Observer,但是并不代表它们不存在(实际上是可以任意扩展的)。

当然,在系统中,WeatherData也只是数据变化的一部分,如果有两部分或者更多,我们可以继续有OtherData...,让它继承自Subject就好了。Subject中定义的方法addObserver可以被forecastObserver显式的调用将自己添加到WeatherData主题中,这样,WeatherData更新的数据就会在notifyobserver中以update的方式更新到forecastObserver中。

至于forecastObserver中的Subject sub元素,就是作为一个观察者,我最起码应该知道我订阅了谁的出版吧,即使以后去退订,也应该知道找谁(调用谁的方法)。

三:实现如下

Subject.java

public interface Subject {

    public void addobserver(Observer ob);
    public void delobserver(Observer ob);
    public void notifyobserver();

}

Observer.java

public interface Observer {
    public void update(int a,int b,int c);
}

WeatherData.java

public class WeatherData implements Subject {
    private ArrayList arrayList = new ArrayList();
    private int x;
    private int y;
    private int z;


    public void addobserver(Observer ob) {
        arrayList.add(ob);

    }

    public void delobserver(Observer ob) {
        int i = arrayList.indexOf(ob);
        if(i >= 0) {
            arrayList.remove(i);
        }
    }

    public void notifyobserver() {
        for (int i = 0; i < arrayList.size(); i++) {
            Observer ob = (Observer) arrayList.get(i);
            ob.update(x,y,z);
        }

    }

    public void setvalue(int a,int b,int c) {
        this.x = a;
        this.y = b;
        this.z = c;
        notifyobserver();
    }
}

forecastObserver.java

public class forecastObserver implements Observer {
    private Subject myobj;
    private int x;
    private int y;

    public forecastObserver(Subject ob) {
        this.myobj = ob;               //保存自己的出版者
        ob.addobserver(this);
    }

    public void update(int a, int b, int c) {
        this.x = a;
        this.y = b;
        display();
    }
    public void display() {
        System.out.println("x is " + x + "  y is " + y);
    }


}

main.java

public class main {
    public static void main(String[] args) {
        WeatherData wd = new WeatherData();    //定义出版者

        forecastObserver fo = new forecastObserver(wd); //订阅者

        wd.setvalue(1,2,3);          //出版者不断变化新的数据
        wd.setvalue(4,5,6);
        wd.setvalue(7,8,9);
    }
}

结果如下:

这里写图片描述

四:总结

好处:

  • 面向接口编程,组合要比继承好。
  • 无论是订阅者增加还是观察者增加都非常容易扩展。

缺点:

  • 数据的更新是被动的。会将不需要的数据一并更新过来,比如上面栗子中forecastObserver不需要z数据,但是Subject还是将数据更新过来了。

五:后续工作

  • 将此模式更改为可以主动数据的。
  • JDK内置观察者模式,改天试一试。
作者:yangbodong22011 发表于2016/11/30 16:28:43 原文链接
阅读:12 评论:0 查看评论