观察者模式(OBSERVER),又称发布-订阅(Publish-Subscribe),依赖(Dependents),通过定义对象间的一对多的依赖关系,达到当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新,属于对象行为型模式。观察者模式在软件设计中很常用,比如经典的MVC模式,Model为目标类,View为观察者,Controller为更新管理器。首先更新管理器即控制器先将视图和模型建立关联关系,然后当模型数据改变时,这些改变会自动反映在视图上,从而达到了业务和显示分离的效果。Java默认支持观察者模式,AWT1.1之后版本,Servlet,SAX2的事件处理模型均为基于观察者模式的委托事件模型(Delegation Event Model或DEM)。在DEM模型里面,主题(Subject)角色负责发布(publish)事件,而观察者角色向特定的主题订阅(subscribe)它所感兴趣的事件。当一个具体主题产生一个事件时,它就会通知所有感兴趣的订阅者。观察者模式提供了一种将发布者与订阅者松散地耦合在一起的联系形式,以及一种能够动态地登记、取消向一个发布者的订阅请求的办法。

一、使用场景

1、当一个抽象模型有两个方面,其中一个方面依赖于另一方面,将这两者封装在独立的对象中以使它们能够独立地改变和复用。

2、当对一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象及这些对象是谁。

3、建立链式触发机制,A影响B,B影响C,C影响D等等。

二、UML图

三、Java实现

[java]  view plain copy
  1. package study.patterns.observer;
  2. import java.text.SimpleDateFormat;
  3. import java.util.ArrayList;
  4. import java.util.Date;
  5. import java.util.List;
  6. /**
  7. * 观察者模式
  8. * @author qbg
  9. */
  10. public class ObserverPattern {
  11. public static void main(String[] args) {
  12. ClockTimerSubject timer = new ClockTimerSubject();//目标
  13. DigitalClock digital = new DigitalClock(timer);//观察者
  14. BigBenClock bigben = new BigBenClock(timer);//观察者
  15. TimerTask task = new TimerTask(timer);//定时任务
  16. task.start();//启动定时任务
  17. }
  18. }
  19. /**
  20. * 抽象目标类
  21. */
  22. abstract class Subject{
  23. protected List<Observer> observers = new ArrayList<Observer>();
  24. /**
  25. *  注册观察者
  26. */
  27. public void attach(Observer obs){
  28. observers.add(obs);
  29. }
  30. /**
  31. * 删除观察者
  32. */
  33. public void detach(Observer obs){
  34. observers.remove(obs);
  35. }
  36. /**
  37. * 通知观察者的抽象方法
  38. */
  39. public abstract void notifyObs();
  40. }
  41. /**
  42. * 具体目标类,每秒更新下自己的内部时间状态
  43. */
  44. class ClockTimerSubject extends Subject{
  45. private String time;
  46. /**
  47. * 具体通知方式,通知所有观察者
  48. */
  49. @Override
  50. public void notifyObs() {
  51. for(Observer obs : this.observers){
  52. obs.update(this);
  53. }
  54. }
  55. /**
  56. * 更新time,并将改变通知给观察者
  57. */
  58. public void tick(){
  59. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  60. time = sdf.format(new Date());
  61. notifyObs();
  62. }
  63. public String getTime() {
  64. return time;
  65. }
  66. public void setTime(String time) {
  67. this.time = time;
  68. }
  69. }
  70. /**
  71. * 观察者抽象接口,只有一个update方法
  72. */
  73. interface Observer{
  74. public void update(ClockTimerSubject subject);
  75. }
  76. /**
  77. * 钟表绘制接口
  78. */
  79. interface Widget{
  80. public void draw();
  81. }
  82. /**
  83. * 数字钟表,具体观察者
  84. */
  85. class DigitalClock implements Widget,Observer{
  86. private ClockTimerSubject subject;
  87. /**
  88. * 初始化目标,并将自己注册到该目标的观察者列表中
  89. */
  90. public DigitalClock(ClockTimerSubject subject){
  91. this.subject = subject;
  92. this.subject.attach(this);
  93. }
  94. /**
  95. * 先检查发出通知的目标是否为自己注册过的,是则响应
  96. */
  97. @Override
  98. public void update(ClockTimerSubject subject) {
  99. if(this.subject == subject){
  100. draw();
  101. }
  102. }
  103. @Override
  104. public void draw() {
  105. System.out.println("电子闹钟为您报时:"+subject.getTime());
  106. }
  107. }
  108. /**
  109. * 大笨钟,具体观察者
  110. */
  111. class BigBenClock implements Widget,Observer{
  112. private ClockTimerSubject subject;
  113. /**
  114. * 初始化目标,并将自己注册到该目标的观察者列表中
  115. */
  116. public BigBenClock(ClockTimerSubject subject){
  117. this.subject = subject;
  118. this.subject.attach(this);
  119. }
  120. /**
  121. * 先检查发出通知的目标是否为自己注册过的,是则响应
  122. */
  123. @Override
  124. public void update(ClockTimerSubject subject) {
  125. if(this.subject == subject){
  126. draw();
  127. }
  128. }
  129. @Override
  130. public void draw() {
  131. System.out.println("伦敦大笨钟为您报时:"+subject.getTime());
  132. }
  133. }
  134. /**
  135. * 定时任务,每秒更新一次ClockTimerSubject的状态
  136. */
  137. class TimerTask extends Thread{
  138. private ClockTimerSubject timer;
  139. public TimerTask(ClockTimerSubject timer){
  140. this.timer = timer;
  141. }
  142. @Override
  143. public void run() {
  144. while(true){
  145. try {
  146. timer.tick();
  147. Thread.sleep(1000);
  148. } catch (InterruptedException e) {
  149. e.printStackTrace();
  150. }
  151. }
  152. }
  153. }

运行结果:

[plain]  view plain copy
  1. 电子闹钟为您报时:2014-02-12 21:44:48
  2. 伦敦大笨钟为您报时:2014-02-12 21:44:48
  3. 电子闹钟为您报时:2014-02-12 21:44:49
  4. 伦敦大笨钟为您报时:2014-02-12 21:44:49
  5. 电子闹钟为您报时:2014-02-12 21:44:50
  6. 伦敦大笨钟为您报时:2014-02-12 21:44:50
  7. 电子闹钟为您报时:2014-02-12 21:44:51
  8. 伦敦大笨钟为您报时:2014-02-12 21:44:51

四、模式优缺点

优点:

1、目标和观察者间的抽象耦合。目标仅知道它有一系列符合抽象接口Observer的观察者,而不知道这些观察者属于哪个具体的类,这样目标和观察者之间的耦合就是抽象的和最小的。

2、支持广播通信。观察目标会向所有已注册的观察者对象发送通知,具体如何处理通知由观察者决定,简化了一对多系统的设计难度。

缺点:

1、意外的更新。由于观察者仅仅知道目标改变了,而不晓得具体什么被改变了,目标上的一个看似无害的操作可能会引起一系列对观察者及依赖于这些观察者的对象的更新,导致错误的产生。

转载于:http://blog.csdn.net/qbg19881206/article/details/19132873

设计模式初探-观察者模式(OBSERVER)又称发布-订阅(Publish-Subscribe)依赖(Dependents)相关推荐

  1. RabbitMQ教程 3.发布/订阅(Publish/Subscribe)

    搜索:Java课代表,关注公众号,及时获取更多Java干货. 3 发布/订阅(Publish/Subscribe) 在上一节中,我们创建了一个工作队列.其目的是将每个任务只分发给一个worker.本节 ...

  2. RabbitMq 发布订阅 Publish/Subscribe fanout/direct

    目录 概述 交换机 临时队列 代码 概述 在上篇中了解到rabbitmq 生产者生产消息到队列,多个消费者可以接受.这篇文章主要记录广播类型为fanout.生产者不在将产生的消息发送到队列,而是将消息 ...

  3. 设计模式初探-观察者模式

    观察者模式(OBSERVER),又称发布-订阅(Publish-Subscribe),依赖(Dependents),通过定义对象间的一对多的依赖关系,达到当一个对象的状态发生改变时,所有依赖于它的对象 ...

  4. 设计模式:观察者模式--Observer

    一.什么是观察者模式 1.生活中的观察者模式 1.警察抓小偷 在现实生活中,警察抓小偷是一个典型的观察者模式「这以一个惯犯在街道逛街然后被抓为例子」,这里小偷就是被观察者,各个干警就是观察者,干警时时 ...

  5. Redis发布与订阅——PUBLISH SUBSCRIBE

    2019独角兽企业重金招聘Python工程师标准>>> Redis发布与订阅--PUBLISH  & SUBSCRIBE 一般来说,发布与订阅(又称pub/sub)的特点是 ...

  6. 锈才学设计模式之 —— 观察者模式(Observer Pattern)

    锈才学设计模式之  -- 观察者模式 观察者模式:定义对象的一对多的关系,这样当主题对象改变状态时,其它的观察者对象都会收到通知,自动更新. 说明: 在真实世界中存在很多类似的模型,比如:订报纸,找中 ...

  7. 设计模式学习--观察者模式(Observer Pattern)

    设计模式学习--观察者模式(Oberser Pattern) 2013年5月18日 天气:热!  下午15:28  设计模式学习中 学习者:小巫 什么是观察者模式? 定义了对象之间的一对多依赖,这样一 ...

  8. Android开发中常见的设计模式深入浅出——观察者模式Observer

    ##最近老大写的Android项目里用到了RxBus然后我就去百度了 让我先了解RxJava 然后RxJava又是由观察者模式的变种写的 所以打算从头学一遍!!! 观察者模式 Observer 顾名思 ...

  9. 设计模式之观察者模式(Observer)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

最新文章

  1. Content-type的说明即HTTP请求头的类型整理
  2. 模拟时钟中断的产生及设计一个对时钟中断事件进行处理的模拟程序_操作系统基础6-支持操作系统的最基本的硬件-中断...
  3. 牛客网编程题06--取近似值
  4. Python模块学习 ---- zlib 数据压缩
  5. linux dd克隆系统后,Ubuntu14.04 dd命令克隆系统镜像安装到另一台机器上
  6. UIView layer 的对应关系
  7. php_redis配置安装php_redis-5.1.1-7.4-nts-vc15-x64.zip
  8. linux查看是否安装了dns,Linux系统怎么查看和修改DNS配置
  9. vue设置浏览器顶部小图标
  10. 如何看待腾讯市值(按 2012 年 8 月 17 日股价)超过 Facebook?
  11. 海德汉 LSV2 协议采集
  12. Android名片识别
  13. 三维CAD设计软件的核心技术解析----工业软件讲坛第二次讲座
  14. 级联(cascade)
  15. 《Unity着色器和屏幕特效开发秘笈》—— 第3章 利用镜面反射让游戏闪耀起来...
  16. Grating Period and Grating Constant(光栅周期与光栅常数)
  17. Linux内核(10) - 内核中的链表
  18. 淘宝 登录 3步登录 取得cookie的方式
  19. linux设置java环境变量_linux配置java环境变量
  20. pythonnet调用python tsne算法

热门文章

  1. 【2022-05-31】JS逆向之易企秀
  2. ssrender例子
  3. 磁共振检查头部能检测出什么_磁共振检查头部的注意事项
  4. springboot定时器@Scheduled的cron,fixedRate,fixedDelay使用
  5. 小程序记账项目源码-采用云开发
  6. 初入Linux——软件安装
  7. 2023牛寒5--小沙の赌气
  8. 为人“着想”和站在别人的角度--7-11创始人的经营理念引发的管理思考
  9. 给Docker NodeRed 设置登陆账户
  10. Cadence(virtuoso)集成电路设计软件基本操作——库管理