生活中,许多事物不是单独存在的,其中一个事物发生变化可能会导致一个或多个其他事物的行为也发生变化。例如:公众号的博主与用户之间(每当推送一篇文章,我们就能被动的接收到一篇文章,前提是你关注了它)。在软件设计中也是一样,例如:MVC 模式中的模型与视图的关系。此类场景使用观察者模式来实现的话,就非常方便。

一、观察者模块的定义与优缺点

观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

观察者模式的优点如下:①、降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。②、目标与观察者之间建立了一套触发机制。

观察者模式的缺点如下:①、目标与观察者之间的依赖关系并没有完全解除。②、当观察者对象很多时,通知的发布会花费很长时间,影响程序的效率。③、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。④、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

二、观察者模式的结构与类图

实现观察者模式时,需要注意具体目标对象和具体观察者对象之间不能直接调用,否则会使两者之间紧密耦合起来,这违反了面向对象的设计原则。

观察者模式主要包含以下角色:【1】抽象主题角色(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

【2】具体主题角色(Concrete Subject):也叫具体目标类,它实现了抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

【3】抽象观察者角色(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

【4】具体观察者角色(Concrete Observer):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

三、观察者模式案例分析

【1】抽象主题角色(Subject):包含对观察者对象的增加、删除和通知等方法的抽象接口。

1 //抽象主题类

2 public interfaceISubject {3 //添加观察者对象

4 public voidaddObserver(IObserver o);5 //删除观察者对象

6 public voidremoveObserver(IObserver o);7 //通知方法

8 public voidnotifyObserver();9 }

【2】具体主题角色(Concrete Subject):需要创建一个集合,存放观察者对象。并实现 ISubject 接口,并实现增删和通知方法。同时添加修改数据的方法 setDate。

1 public class SubjectImpl implementsISubject{2 private String name;//博客名

3 private String content;//博客内容

4 private String type;//博客类型

5

6 public voidsetDate(String name,String content,String type) {7 this.name=name;8 this.content=content;9 this.type =type;10 }11

12 //定义一个集合存放 观察者对象

13 Listobservers;14

15 //构造器

16 publicSubjectImpl() {17 observers = new ArrayList();18 }19 //添加

20 @Override21 public voidaddObserver(IObserver o) {22 observers.add(o);23 }24 //删除

25 @Override26 public voidremoveObserver(IObserver o) {27 observers.remove(o);28 }29

30 @Override31 public voidnotifyObserver() {32 for(IObserver iObserver : observers) {33 if(iObserver != null) {34 iObserver.update(name,content,type);35 }36 }37 }38 }

【3】抽象观察者角色(Observer):抽取观察者们的共同方法 update 获取目标对象传递过来的信息。

1 //抽象观察者

2 public interfaceIObserver {3 //接受主题类的信息

4 public voidupdate(String name,String content,String type);5 }

【4】具体观察者角色(Concrete Observer):实现抽象的观察者角色,并获取目标对象传递的值,进行逻辑处理。

1 public class ObserverImpl_A implementsIObserver{2

3 @Override4 public voidupdate(String name, String content, String type) {5 //对接受到的信息进行逻辑处理

6 System.out.println("===观察者A====");7 System.out.println("***博客名称 : " + name + "***");8 System.out.println("***博客内容: " + content + "***");9 System.out.println("***博客类型: " + type + "***");10 }11 }

【5】客户端:创建目标对象和观察者对象,并将观察者对象添加到目标对象的观察者集合中,并进行通知。

1 public classClient {2

3 public static voidmain(String[] args) {4 //目标对象 博客博主

5 SubjectImpl subjectImpl = newSubjectImpl();6 //创建观察者对象 用户A

7 ObserverImpl_A observerImpl_A = newObserverImpl_A();8 //将观察对象 关注 表表对象

9 subjectImpl.addObserver(observerImpl_A);10 //博客开始更新博客

11 subjectImpl.setDate("Java设计模式", "访问者模式", "技术类");12 //通知观察者 关注的用户门

13 subjectImpl.notifyObserver();14 }15 }

四、观察者模式扩展优点

【1】只需要新增观察者对象类。

1 packageobsever;2

3 public class ObserverImpl_B implementsIObserver{4

5 @Override6 public voidupdate(String name, String content, String type) {7 //对接受到的信息进行逻辑处理

8 System.out.println("===观察者B====");9 System.out.println("***博客名称 : " + name + "***");10 System.out.println("***博客内容: " + content + "***");11 System.out.println("***博客类型: " + type + "***");12 }13 }

【2】客户端调用时,将其注册到目标对象中即可。符合 OCP 原则。

1 ObserverImpl_B observerImpl_B = newObserverImpl_B();2 //将观察对象 关注 表表对象

3 subjectImpl.addObserver(observerImpl_B);

五、观察者模式应用源码分析

【1】查看一下 Observable 的源码,发现 Observable 是一个具体的主题类,此处与我们的例子不同之处是没有实现接口,我们细想也会发现,其实主题类也无需实现接口。

1 public classObservable {2 private Vectorobs;3

4 /**创建集合 存放观察者对象 Observer*/

5

6 publicObservable() {7 obs = new Vector<>();8 }9 //添加

10 public synchronized voidaddObserver(Observer o) {11 if (o == null)12 throw newNullPointerException();13 if (!obs.contains(o)) {14 obs.addElement(o);15 }16 }17 //删除

18 public synchronized voiddeleteObserver(Observer o) {19 obs.removeElement(o);20 }21 //通知

22 public voidnotifyObservers() {23 notifyObservers(null);24 }25 public voidnotifyObservers(Object arg) {26

27 Object[] arrLocal;28

29 synchronized (this) {30

31 if (!changed)32 return;33 arrLocal =obs.toArray();34 clearChanged();35 }36 //循环调用 观察者对象的 update 通知方法

37 for (int i = arrLocal.length-1; i>=0; i--)38 ((Observer)arrLocal[i]).update(this, arg);39 }

【2】抽象观察者接口 Observer。

1 public interfaceObserver {2 voidupdate(Observable o, Object arg);3 }

java 观察者模式类图_设计模式——观察者模式相关推荐

  1. java观察者模式类图_设计模式(十八)——观察者模式(JDK Observable源码分析)...

    1 天气预报项目需求,具体要求以下: 1) 气象站能够将天天测量到的温度,湿度,气压等等以公告的形式发布出去(好比发布到本身的网站或第三方).java 2) 须要设计开放型 API,便于其余第三方也能 ...

  2. java 计算器类图_多态计算器(封装、继承、多态、简单工厂)

    一.封装 向对象程序设计中,一个非常重要的技术便是封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏.这样做的好处在于可以使类内部的具体 ...

  3. java流类图结构_java I/O 流总结

    一.java 流操作有关的类和接口: 类                                                                          说明 Fil ...

  4. java流类图结构_java学习之IO流(学习之旅,一)

    个人在学习IO流的时候看到如下所示java 流类图结构的时候,我的感想是,这么多··处于蒙的状态. Java流类图结构 这么多,没有分类不好学,那我们就慢慢一口一口的吃,这样每天学习一点就好了,其实很 ...

  5. 观察者模式java类图_初探Java设计模式------观察者模式

    前言 最近刚开始学习RxJava,众所周知,Rxjava就是扩展的观察者模式,所以想学习Rxjava,先入手了解一下观察者模式是很有必要的.那么今天就先稍微了解一下什么是观察者模式. 定义 观察者(O ...

  6. java 外观模式类图_Java 设计模式——外观模式

    概述 今天要说的外观模式是一个相对简单的设计模式,而且在日常的开发中,可能你也会时常使用它,只是你可能并未想过这是一个设计模式.本文会从一些实例着手,来对本文要说明的外观模式进行尽可能全面的讲解.希望 ...

  7. java 类爆炸_设计模式系列·类爆炸之 Bridge 模式

    迷之微笑 经过 C 哥的精心指导,消息中心终于上线!代码运行了半个月,稳健无 bug . 王小二托着下腮,看着代码,一抹迷之微笑随之闪现^_^.作为一名有追求的码农,此时的快乐或许只有自己能懂. 消息 ...

  8. 单例模式访问mysql设计类图_如何应用策略设计模式分离JDBC数据库连接中的外部环境信息...

    软件项目实训及课程设计指导--如何应用策略设计模式分离JDBC数据库连接中的外部环境信息 1.什么是策略(Strategy)设计模式 策略设计模式把"算法"(也就是软件应用系统中的 ...

  9. startuml java 类图_【StarUML】类图

    类图是可视化地表现类的属性和方法,以及类与类之间的关系. 1.类 a.类 普通实体类,它有对应的属性和方法: 双击类名,会弹出一些控制按钮: 右边区域,各个图标的含义依次是: 增加类的属性.增加类的操 ...

  10. visio uml 画java类图_用visio画UML类图

    对于画类图的工具很多,曾经学过用starUML画类图,但这个是用于Java语言的,对于用vs编程C++语言,个人感觉用visio会好一点.以下用以前面的俄罗斯方块游戏中的一个Block类为例来讲述 c ...

最新文章

  1. Audio: 如果你愿意一层一层剥开我的心
  2. ECSHOP发送邮件提示need rcpt command的解决方法
  3. Safari 版本回退方法
  4. Scroll Depth – 衡量页面滚动的 Google 分析插件
  5. 设定Word段落的背景色
  6. 2021年低碳科技白皮书
  7. jQuery仿京东首页广告图片切换图片轮播
  8. CSS3给页面打标签
  9. java jxl label_jxl.write.label
  10. SpringBoot(三) SpringBoot中的日志配置
  11. eclipse windowJAVA版64位安装教程
  12. 六度空间-c++实现
  13. 【兴趣书签】为什么观测之后量子态会坍塌
  14. MySQL的各种安装方式都给你
  15. (数据库系统)(十二)故障恢复
  16. Windows混音器API使用
  17. 设置ListView中的所有Item均不可点击
  18. 阿里员工发帖吐槽人不如驴,“阿里驴学”究竟是什么?
  19. 计算机考研怎么给老师发邮件,考研复试前,手把手教你怎么给导师发邮件!4点要注意...
  20. html页面其中有添加员工的,编写一个添加员工信息的HTML页面,当用户点击添加按钮,请求AddEmpServlet,实现将用户提交的员工基本信息返回给客户端显示出来。...

热门文章

  1. 计算机ppt闪耀效果在哪里,ppt怎样制作文字闪烁效果
  2. 2022电工(初级)考试模拟100题模拟考试平台操作
  3. 2022年N1叉车司机考试题及N1叉车司机理论考试
  4. NB-IoT开发都涉及什么
  5. 测试开发面试题(一)-----appium相关
  6. Java第四课:用类描述CPU速度和HardDisk容量
  7. vim 插件安装 (ubuntu OS)
  8. 共聚焦扫描显微镜的工作原理
  9. PR免费转场 动态图形转场PR模板MOGRT免费下载
  10. python下载加密m3u8_基于Python3实现的m3u8批量下载器 解密合并多线程 (开车新姿势~)...