java设计模式之观察者模式

来源:互联网 发布:php布尔类型 编辑:程序博客网 时间:2024/06/05 07:37

定义:该模式也成为发布订阅模式,定义如下: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. 也就是说,在对象之间建立起一种一对多的关系使得该对象自身状态发生变化时其他对象均能得到通知并自动更新。
其所应用的环境就是,有多个类需要监控某一个类的执行状态。我们所能想到的第一方法往往是在监控类中新起一个线程,专门用于监控被监控类的执行状态,然而这种方式过于耗费系统资源,并不是一种好的实现方式。而此时,观察者模式就是为了解决这种问题而存在的。
首先来看看一个示例类图:
这里写图片描述
该类图所示的结构,建立在这样一个故事背景下:一个囚犯(Prisoner对象)被关押在牢狱里,负责监管他的有警察(Police对象)以及警官(Officer对象),每当囚犯打算逃跑时,警察和警官需及时作出反应。
上面所示的类图也是观察者模式常用的构造方式。充分考虑系统的可扩展性,先创建两个接口定义观察者与被观察者遵循的规范。其中Observer接口定义观察者行为规范,Observabel接口定义被观察者行为规范,一般包括添加、删除与通知观察者方法。而观察者与被观察者是如何建立起观察关系的呢?我们来看Prisoner类,其定义了一个私有变量,定义了一个数组用于记录所有的观察者。在自己的行为代码中,例如run()逃跑方法中调用notifyAllObservers()方法,通知所有观察者对象,在notifyAllObservers()方法中调用对应观察者的update()方法,更新观察者自身状态,从而达到观察的作用。
其示例代码如下:
观察者接口:

public interface Observer {    //更新操作    public void update(String txt);}

被观察者接口:

public interface Observabel {     void addObserver(Observer observer);     void removeObserver(Observer observer);     void notifyAllObservers(String context);}

观察者——警察:

public class Police implements Observer {    public void update(String txt) {        System.out.println("Police 发现"+txt);    }}

观察者——警官:

public class Officer implements Observer{    public void update(String txt) {        System.out.println("Officer 发现"+txt);    }}

被监管者——囚犯:

public class Prisoner implements Observabel{    private ArrayList<Observer> observers = new ArrayList<Observer>();    public void addObserver(Observer observer) {        this.observers.add(observer);    }    public void removeObserver(Observer observer) {        this.observers.remove(observer);    }    public void notifyAllObservers(String context) {        for (Observer obs:this.observers) {            obs.update(context);        }    }    public void run(){        System.out.println("囚犯:我要偷偷逃跑");        this.notifyAllObservers("囚犯要逃跑啦");    }}
Main方法:
    public class Main {    public static void main(String [] args){        Police police = new Police();        Officer officer = new Officer();        Prisoner prisoner = new Prisoner();        prisoner.addObserver(police);        prisoner.addObserver(officer);        prisoner.run();    }}

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

  1. 观察者与被观察者之间是抽象耦合关系
  2. 建立了一整套触发机制,在必要的情况下,可建立多级观察结构,从而形成链式触发
    问题:

  3. 广播链设计问题,上述的广播是通过遍历数组,逐步实现的,但需要注意不能出现环式观察结构,要不然系统将不停地触发下一环节了。

  4. 异步处理问题,在上面的例子中也是由于是串行更新观察者状态,一旦一个环节崩溃了,则接下来的观察者也都将得不到更新。且如果观察者较多的情况下,这个过程将极为耗时。解决这个问题,需考虑使用异步处理(参考消息队列实现方式,这个后续说明)。

    需要补充说明的是,JDK已经提供了一个java.util.Observabel类以及java.util.Observer接口,所以上面的例子中的Observabel和Observer接口均可以直接被替代,就不用自己实现增加、删除以及通知观察者的方法逻辑了。需要说明的是,被观察者在通知观察者之前,需调用Observabel类中的setChanged()方法更新观察者列表,然后再调用notifyObservers()方法。
    应用环境:当业务逻辑可以被拆分为多个独立的逻辑类,且相互之间存在这种链式触发关系,则最好采用这种观察者模式来设计相关业务功能。例如文件系统中,新建一个文件事件就可以作为被观察者,目录管理器作为观察者,这时将增加该目录,同时内存管理器也作为观察者,减少对应剩余内存。

0 0