一、Observer模式的意图:

在对象的内部状态发生变化时,自动通知外部对象进行响应。

二、Observer模式的构成:

·被观察者:内部状态有可能被改变,而且又需要通知外部的对象

·观察者:需要对内部状态的改变做出响应的对象

三、Observer模式的Java实现:

Java的API中已经为我们提供了Observer模式的实现。具体由java.util.Observable类和java.util.Observer接口完成。

前者有两个重要的方法:

·setChanged:设置内部状态为已改变

·notifyObservers(Object obj):通知观察者所发生的改变,参数obj是一些改变的信息

后者有一个核心方法:

·update(Object obj):相应被观察者的改变,其中obj就是被观察者传递过来的信息,该方法会在notifyObservers被调用时自动调用。

下面是Observer模式的实现过程:

·创建一个被观察者,继承java.util.Observable

·创建一个观察者,实现java.util.Observer接口

· 注册观察着,调用addObserver(Observer observer)

·在被观察者改变对象内部状态的地方,调用setChanged()方法,然后调用notifyObservers(Object)方法,通知被观察者

·在观察者的update(Object)方法中,对改变做出响应。

四、Observer模式的好处:

1.Observer模式的优点:

·被观察者只需要知道谁在观察它,无需知道具体的观察细节

·被观察者一旦发生变化,只需要通过广播的方式告知观察者,至于消息如何到达则不需知道。这样的话无疑消除了被观察者和观察者之间通信的硬编码

·当一个被观察者同时被多个观察着观察时,观察者可以只选择自己感兴趣的事件,而忽略其它的事件
   
                      ·多个观察者组合起来可以形成一个观察链,如果一旦需要回滚多个操作,此时观察链可以发挥作用

·观察者可以实时对被观察对象的变化做出响应,例如自动告警、中断运行等

2.运用Observer模式可以

·屏蔽线程间的通信机制:例如两个线程之间,主线程可以作为观察者,执行线程是被观察者。彼此之间只知道对方存在,但不知道之间通信的细节

·消除硬编码:如果没有Observer模式,则只能采用回调的模式,或者在代码中显示地调用观察者

·优化异常机制:特别适合在异常发生时向顶层监控,减少try-catch代码量

代码:

  1. public class Observable {
  2. private boolean changed = false;
  3. private Vector obs;
  4. //创建被观察者时就创建一个它持有的观察者列表,注意,这个列表是需要同步的。
  5. public Observable() {
  6. obs = new Vector();
  7. }
  8. /**
  9. * 添加观察者到观察者列表中去
  10. */
  11. public synchronized void addObserver(Observer o) {
  12. if (o == null)
  13. throw new NullPointerException();
  14. if (!obs.contains(o)) {
  15. obs.addElement(o);
  16. }
  17. }
  18. /**
  19. * 删除一个观察者
  20. */
  21. public synchronized void deleteObserver(Observer o) {
  22. obs.removeElement(o);
  23. }
  24. /**
  25. * 通知操作,即被观察者发生变化,通知对应的观察者进行事先设定的操作,不传参数的通知方法
  26. */
  27. public void notifyObservers() {
  28. notifyObservers(null);
  29. }
  30. /**
  31. * 与上面的那个通知方法不同的是,这个方法接受一个参数,这个参数一直传到观察者里,以供观察者使用
  32. */
  33. public void notifyObservers(Object arg) {
  34. Object[] arrLocal;
  35. synchronized (this) {
  36. if (!changed)
  37. return;
  38. arrLocal = obs.toArray();
  39. clearChanged();
  40. }
  41. for (int i = arrLocal.length-1; i>=0; i--)
  42. ((Observer)arrLocal[i]).update(this, arg);
  43. }
  44. }
  45. public interface Observer {
  46. /**
  47. * This method is called whenever the observed object is changed. An
  48. * application calls an <tt>Observable</tt> object's
  49. * <code>notifyObservers</code> method to have all the object's
  50. * observers notified of the change.
  51. *
  52. * @param   o     the observable object.
  53. * @param   arg   an argument passed to the <code>notifyObservers</code>
  54. *                 method.
  55. */
  56. void update(Observable o, Object arg);
  57. }
  58. }
  59. public class MailObserver implements Observer{
  60. /**
  61. * 这个类取名为MailObserver,顾名思义,她是一个用来发送邮件的观察者
  62. */
  63. public void update(Observable o, Object arg) {
  64. System.out.println("发送邮件的观察者已经被执行");
  65. }
  66. }
  67. public class JMSObserver implements Observer{
  68. public void update(Observable o, Object arg) {
  69. System.out.println("发送消息给jms服务器的观察者已经被执行");
  70. }
  71. }
  72. public class Subject extends Observable{
  73. /**
  74. * 业务方法,一旦执行某个操作,则通知观察者
  75. */
  76. public void doBusiness(){
  77. if (true) {
  78. super.setChanged();
  79. }
  80. notifyObservers("现在还没有的参数");
  81. }
  82. public static void main(String [] args) {
  83. //创建一个被观察者
  84. Subject subject = new Subject();
  85. //创建两个观察者
  86. Observer mailObserver = new MailObserver();
  87. Observer jmsObserver = new JMSObserver();
  88. //把两个观察者加到被观察者列表中
  89. subject.addObserver(mailObserver);
  90. subject.addObserver(jmsObserver);
  91. //执行业务操作
  92. subject.doBusiness();
  93. }
  94. }

在spring中使用观察者模式的方法如下

<bean id="mailObserver" class="MailObserver"/>    
      
  <bean id="jmsObserver" class="JMSObserver"/>    
      
  <bean id="subjectTarget" class="Subject"/>    
      
  <bean id="subject"   
         class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">    
         <property name="targetObject"><ref local="subjectTarget"/></property>    
         <property name="targetMethod"><value>addObserver</value></property>    
         <property name="arguments">    
           <list>    
              <ref bean="mailObserver"/>    
              <ref bean="jmsObserver"/>    
           </list>    
        </property>    
  </bean>   
观察者模式的效果有以下几个优点:

(1)观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者 的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象 化层次。

(2)观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。

观察者模式有下面的一些缺点:

(1)如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

(2)如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。

(3)如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

(4)虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的

 

Java Observable 模式的更多相关文章

  1. 设计模式--观察者模式初探和java Observable模式

    初步认识观察者模式 观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明: 报社方负责出版报纸. 你订阅了该报社的报纸,那么只要报社发布了新报 ...

  2. 《JAVA与模式》之观察者模式

    转自:http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html 在阎宏博士的<JAVA与模式>一书中开头是这样 ...

  3. <代码整洁之道>、<java与模式>、<head first设计模式>读书笔记集合

    一.前言                                                                                       几个月前的看书笔记 ...

  4. 《JAVA与模式》之观察者模式(转载)

    <JAVA与模式>之观察者模式(转载)  原文链接:http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html ...

  5. java future模式 所线程实现异步调用(转载

    java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...

  6. JAVA的模式对话框和非模式对话框

    周末的时候,一位网友让我帮他把他的无模式对话框改成有模式对话框. 界面是由swing制作的,都是JFrame,我从来没有接触过swing编程.大致的代码还是看的懂,很多都和C#很相似. 然后就去查资料 ...

  7. java工厂模式

    (1)概念大白话:java工厂模式就是客户端(main函数)要创建对象觉得麻烦就让另外一个叫工厂的类帮它创建,然后自己每次要创建对象就叫工厂帮它弄,举个例子,在没有工厂这个"手下" ...

  8. 《JAVA与模式》之单例模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述单例模式的: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的 ...

  9. Java代理模式

    java代理模式及动态代理类 1.      代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目 ...

随机推荐

  1. Jenkins配置基于角色的项目权限管理--转

    本文将介绍如何配置jenkins,使其可以支持基于角色的项目权限管理. 由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,本文将使用Role Str ...

  2. ANDROID STUDIO, GRADLE AND NDK INTEGRATION

    Originally posted on:http://ph0b.com/android-studio-gradle-and-ndk-integration/ With the recent chan ...

  3. linux下如何查看和修改系统BLOCK的大小

    http://blog.163.com/drachen@126/blog/static/162607494201271435333906/ 查看os系统块的大小 [root]# /sbin/tune2 ...

  4. Hadoop基础教程之重新认识Hadoop

      之前,我们把hadoop从下载包部署到编写了helloworld,看到了结果.现是得开始稍微更深入地了解hadoop了. Hadoop包含了两大功能DFS和MapReduce, DFS可以理解为一 ...

  5. Hibernate笔记——表的的4种继承关系

    原文:http://justsee.iteye.com/blog/1070588 ===================================== 一.继承关系_整个继承树映射到一张表 对象 ...

  6. #-webkit-autofill##google#启用表单自动填充时,如何覆盖黄色背景

    google和opera浏览器的表单自动填充后,输入框均会变成黄色背景,黑色字体.如下图. 这样的话会与网页的整体设计风格不一致,怎样自定义样式,来覆盖黄色背景. 首先来看看是什么导致的,右键查看元素 ...

  7. Help Jimmy--poj1661(dp)

    题目链接:http://poj.org/problem?id=1661 下图是左边的,右边的同理: #include<stdio.h> #include<string.h> # ...

  8. 277. Find the Celebrity

    题目: Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exi ...

  9. Python 时间戳与时间字符串互相转

    #设a为字符串 import time a = "2011-09-28 10:00:00" #中间过程,一般都需要将字符串转化为时间数组 time.strptime(a,'%Y-% ...

  10. poj -1065 Wooden Sticks (贪心or dp)

    http://poj.org/problem?id=1065 题意比较简单,有n跟木棍,事先知道每根木棍的长度和宽度,这些木棍需要送去加工,第一根木棍需要一分钟的生产时间,如果当前木棍的长度跟宽度 都 ...