java 观察者模式

java观察者模式介绍

概念html

 Observer模式定义对象间的一对多的依赖关系,当一个对象(被观察者)的状态发生改变时, 全部依赖于它的对象(观察者)都获得通知并被自动更新。JDK里提供的observer设计模式的实现由java.util.Observable类和 java.util.Observer接口组成。从名字上能够清楚的看出二者在Observer 设计模式中分别扮演的角色:Observer是观察者角色,Observable是被观察目标(subject)角色。java

相关类介绍web

1.Obervable设计模式

此类表示模型视图范例中的 observable 对象,继承它的类表示应用程序想要观察的对象。一个 observable 对象能够有一个或多个观察者。观察者是实现Observer接口的任意对象。一个 observable 实例改变后,调用 Observable 的 notifyObservers 方法的应用程序会经过调用观察者的 update 方法来通知观察者该实例发生了改变。安全

方法摘要框架

 voidide

addObserver(Observer o) 
          若是观察者与集合中已有的观察者不一样,则向对象的观察者集中添加此观察者。未指定向多个观察者发送通知的顺序。post

protected  void性能

clearChanged() 
          指示对象再也不改变,或者它已对其全部的观察者通知了最近的改变,因此 hasChanged 方法将返回 false。notifyObservers 方法自动调用此方法。测试

 int

countObservers() 
          返回 Observable 对象的观察者数目。

 void

deleteObserver(Observer o) 
          从对象的观察者集合中删除某个观察者。向此方法传递 null无效。

 void

deleteObservers() 
          清除观察者列表,使此对象再也不有任何观察者。

 boolean

hasChanged() 
          测试对象是否改变。当且仅当在此对象上最近调用了 setChanged 方法时才返回 true;不然返回 false。

 void

notifyObservers() 
          若是 hasChanged 方法指示对象已改变,则通知其全部观察者,并调用 clearChanged 方法来指示此对象再也不改变。

每一个观察者都有其 update 方法,其调用参数有两个:observable 对象和 null。换句话说,此方法等效于: notifyObservers(null)

 void

notifyObservers(Object arg) 
          若是 hasChanged 方法指示对象已改变,则通知其全部观察者,并调用 clearChanged 方法来指示此对象再也不改变。

每一个观察者都有其 update 方法,其调用参数有两个:observable 对象和 arg 参数。 arg 能够是任意对象

protected  void

setChanged() 
          标记此 Observable 对象为已改变的对象;如今 hasChanged 方法将返回 true

 

关于发送通知的顺序

Observable 类中所提供的默认实现将按照其注册的重要性顺序来通知 Observers,可是子类可能改变此顺序,从而使用非固定顺序在单独的线程上发送通知,或者也可能保证其子类听从其所选择的顺序。

注意:此通知机制与线程无关,而且与 Object 类的 wait  notify 机制彻底独立。

新建立一个 observable 对象时,其观察者集是空的。当且仅当 equals 方法为两个观察者返回 true 时,才认为它们是相同的。

 

2.Oberver接口

这是个接口类,这个接口只有一个为实现的抽象方法update。实现该接口的对象成为观察者,该对象要实现update方法。注册了该对象(观察者)的对象(观察者)实例条用notifiyObservers方法后,观察者会自动执行update方法。

方法摘要

 void

update(Observable o, Object arg) 
          只要改变了 observable 对象就调用此方法。

o - observable 对象。

arg - notifyObservers 方法的参数。

 

实例

该实例模拟了烧水的过程,涉及三个对象,Heater(热水器),Display(显示器),Alarm(报警器).

模拟过程:为了便于运行,水的初始化温度为90,沸点为95,显示器依据热水器显示温度,显示器显示温度为95时,报警器开始报警。明显能够看出Heater是subject ,Display 是它的 Obsrver,同时Display亦是subject,由于它要被报警器观察,因此Alarm是Display的Observer.

 

Heater.java

public class Heater extends Observable {

    private int temperature;

 

    public int getTemperature() {

       return temperature;

    }

 

    public void setTemperature(int temperature) {

       this.temperature = temperature;

    }

 

    public void boilWater() {

       for (int i = 90; i < 110; i++) {

           temperature = i;

       this.setChanged();

       this.notifyObservers();

       }

    }

}

 

Display.java

public class Display extends Observable implements Observer {

    private String status = "未开";

 

    public String getStatus() {

       return status;

    }

 

    public void setStatus(String status) {

       this.status = status;

    }

 

    @Override

    public void update(Observable o, Object arg) {

       this.displayTemperature(((Heater) o).getTemperature());

    }

 

    private void displayTemperature(int temperature) {

       if (temperature > 100) {

           this.setStatus("沸腾");

           this.setChanged();

           this.notifyObservers(temperature);

       }

       System.out.println("状态: " + status + "  如今温度: " + temperature);

    }

}

 

Alarm.java

public class Alarm implements Observer {

    @Override

    public void update(Observable arg0, Object arg1) {

       this.makeAlarm((Integer) arg1);

    }

 

    private void makeAlarm(int temperature) {

       System.out.println("嘀嘀嘀。。。水已经烧开了");

       // System.out.println("如今水温是: " + temperature);

    }

}

 

TestMain.java测试入口类

public class TestMain {

    public static void main(String[] args) {

       Heater heater = new Heater();

       Display display = new Display();

       Alarm alarm = new Alarm();

       heater.addObserver(display);

       display.addObserver(alarm);

       heater.boilWater();

    }

}

优势

  • 支持松耦合和减小依赖性。客户端再也不依赖于观察器,由于经过使用主体和 Observer 接口对客户端进行了隔离。许多框架具备此优势,在这些框架中的应用程序组件能够注册为当(低级)框架事件发生时获得通知。结果,框架将调用应用程序组件,但不会依赖于它。
  • 观察器数目可变。观察器能够在运行时附加和分离,由于主体对于观察器数目没有任何假定。此功能在这样的状况下是颇有用的:观察器数在设计时是未知的。例如,若是用户在应用程序中打开的每一个窗口都须要一个观察器。

缺点

  • 性能下降。在许多实现中,观察器的 update() 方法可能与主体在同一线程中执行。若是观察器列表很长,则执行 Notify() 方法可能须要很长时间。抽取对象依赖性并不意味着添加观察器对应用程序没有任何影响。
  • 内存泄漏。在 Observer 中使用的回调机制(当对象注册为之后调用时)会产生一个常见的错误,从而致使内存泄漏,甚至是在托管的 C# 代码中。假定观察器超出做用范围,但忘记取消对主体的订阅,那么主体仍然保留对观察器的引用。此引用防止垃圾收集在主体对象也被破坏以前从新分配与观察器关联的内存。若是观察器的生存期比主体的生存期短得多(一般是这种状况),则会致使严重的内存泄漏。
  • 隐藏的依赖项。观察器的使用将显式依赖性(经过方法调用)转变为隐式依赖性(经过观察器)。若是在整个应用程序中普遍地使用观察器,则开发人员几乎不可能经过查看源代码来了解所发生的事情。这样,就使得了解代码更改的含意很是困难。此问题随传播级别急剧增大(例如,充当 Subject 的观察器)。所以,应该仅在少数定义良好的交互(如 Model-View-Controller 模式中模型和视图之间的交互)中使用观察器。最好不要在域对象之间使用观察器。
  • 测试 / 调试困难。尽管松耦合是一项重大的体系结构功能,可是它可使开发更困难。将两个对象去耦的状况越多,在查看源代码或类的关系图时了解它们之间的依赖性就越难所以,仅当能够安全地忽略两个对象之间的关联时才应该将它们松耦合(例如,若是观察器没有反作用)。

参考文章:

http://baike.baidu.com/view/6547055.htm

http://msdn.microsoft.com/zh-cn/library/ms978753.aspx

相关文章
相关标签/搜索