一、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 观察者模式 与spring配置的更多相关文章

  1. 开涛spring3(12.4) - 零配置 之 12.4 基于Java类定义Bean配置元数据

    12.4  基于Java类定义Bean配置元数据 12.4.1  概述 基于Java类定义Bean配置元数据,其实就是通过Java类定义Spring配置元数据,且直接消除XML配置文件. 基于Java ...

  2. Spring配置c3p0数据源时出错报:java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector

    今天在使用Spring配置c3p0数据源时,使用的数据库是mysql,服务器是tomcat,运行时报了一个 java.lang.NoClassDefFoundError: com/mchange/v2 ...

  3. 用Spring提高java观察者模式灵活性

    在上篇博客 用java观察者模式解耦经典三层架构 的最后,用了一个Client类把Listener的实现类注冊到了LoginEventSource类中,假设须要加入�新的逻辑,加入�新的listene ...

  4. 基于纯Java代码的Spring容器和Web容器零配置的思考和实现(3) - 使用配置

    经过<基于纯Java代码的Spring容器和Web容器零配置的思考和实现(1) - 数据源与事务管理>和<基于纯Java代码的Spring容器和Web容器零配置的思考和实现(2) - ...

  5. Spring基础篇——通过Java注解和XML配置装配bean

    自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应用程序维护,而是引用了第三方的类库,这个时候自动装配便无法实现,Spring对此也提供了相应的解决方案 ...

  6. java多线程、线程池及Spring配置线程池详解

    1.java中为什么要使用多线程使用多线程,可以把一些大任务分解成多个小任务来执行,多个小任务之间互不影像,同时进行,这样,充分利用了cpu资源.2.java中简单的实现多线程的方式 继承Thread ...

  7. java 线程池(ExecutorService与Spring配置threadPoolTaskExecutor)

    一.java ExecutorService实现 创建ExecutorService变量private ExecutorService executor = null 2.执行对应任务时,首先生成线程 ...

  8. spring 配置 Java配置类装配bean

    https://www.cnblogs.com/chenbenbuyi/p/8457700.html 自动化装配的确有很大的便利性,但是却并不能适用在所有的应用场景,比如需要装配的组件类不是由自己的应 ...

  9. 【Java Web开发学习】Spring配置数据源

    Spring配置数据源 转载:https://www.cnblogs.com/yangchongxing/p/10027495.html =============================== ...

随机推荐

  1. ThinkPHP 5 中的 composer.json

    本篇并不是揭 ThinkPHP 5 的问题. 只是通过 composer.json 来学习 compoer.json 元旦那天, ThinkPHP 5.1 正式发布,值得庆祝. 之后的第二天有人反馈 ...

  2. 【转】每天一个linux命令(52):ifconfig命令

    原文网址:http://www.cnblogs.com/peida/archive/2013/02/27/2934525.html 许多windows非常熟悉ipconfig命令行工具,它被用来获取网 ...

  3. R(1):中文乱码解决方案

    读取csv文件出现中文乱码方案,增加编码格式参数 read.csv(trainPath,header=TRUE,stringsAsFactors=TRUE,encoding = "UTF-8 ...

  4. git提交忽略不必要的文件或文件夹

    创建maven项目,使用git提交,有时需要忽略不必要的文件或文件夹,只保留一些基本. 例如如下截图,实际开发中我们只需提交:src,.gitignore,pom.xml 而自己项目文件一般都保留,但 ...

  5. 【Oracle学习笔记-3】关于Oracle 10g中各种服务解析

    [原创]关于oracle 10g中各种服务解析 (2014/10/16 8:39:40) 时间:2014-10-16 8-58-30     作者:ssslinppp 1. 当首次安装oracle 1 ...

  6. bzoj 3768: spoj 4660 Binary palindrome二进制回文串

    Description 给定k个长度不超过L的01串,求有多少长度为n的01串S满足: 1.该串是回文串 2.该串不存在两个不重叠的子串,在给定的k个串中. 即不存在a<=b<c<= ...

  7. bzoj3157 3516 国王奇遇记

    Description Input 共一行包括两个正整数N和M. Output 共一行为所求表达式的值对10^9+7取模的值. 特判m=1 m≠1时: 设S[u]=sigma(i^u*m^i) m*S ...

  8. XML-RPC简单使用

    RPC(Remote Procedure Call)即远程方法调用,是一种在本地的机器上调用远端机器上的一个过程(方法)的技术.这个过程也被大家称为“分布式计算”,是为了提高各个分立机器的“互操作性” ...

  9. Spring IOC - 控制反转(依赖注入) - 配置初始化和销毁的方法

    在Spring中如果某个bean在初始化之后,或销毁之前要做一些额外操作可以为该bean配置初始化和销毁的我方法,在这些方法中完成需要的功能. 实验: 通过断点调试模式,测试初始化方法和销毁方法的执行 ...

  10. 学习笔记之YAML

    The Official YAML Web Site http://yaml.org/ YAML(tm) is an international collaboration to make a dat ...