前言:

观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自己更新自己。

一.观察者模式简介:

观察者模式(Observer Pattern)应用在当一个对象的改变,需要同时改变其他对象的时候,实现了两个相互协作的对象不会为了保持一致性而耦合在一起,这两个对象都依赖于各自的抽象。

二.观察者模式的实例讲解:

案例:学生们观察老师讲课时的动态,决定是否继续睡觉或者继续抄作业。

1.产品设计UML类图:


(图片加载慢,多刷新几下,耐心等待……)

注:指挥者类ClientObserverSubject的实现类是依赖关系。

2.通知者抽象类(主题类):

设计分析:Subject类把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者,抽象主题增加一个接口,可以增加和删除观察者对象。抽象主题类可以被多个具体主题类继承。

package com.pattern.observer.subject;import com.pattern.observer.observer.Observer;/*** 通知者抽象类*/
public abstract class Subject {// 通知者状态protected String subjectState;// 获取通知者状态public String getSubjectState() {return subjectState;}// 设置通知者状态public void setSubjectState(String subjectState) {this.subjectState = subjectState;}// 添加观察者public abstract void addObserver(Observer observer);// 删除观察者public abstract void removeObserver(Observer observer);// 通知观察者public abstract void notifyObserver();
}

3.老师通知者类(具体主题类):

设计分析: 将有关状态存入观察者对象,在主题内部状态改变的时候,给所有观察者发信息。

在本例中,老师的行为受到所有学生的关注,一旦反生改变,将会通知(notifyObserver())学生改变(update())行为。比如:正在打瞌睡的同学,看到老师过来,会立马打起精神。正在语文课上,抄数学作业的人,会立马收起作业,假装认真的读语文书。

package com.pattern.observer.subject;import java.util.ArrayList;
import java.util.List;import com.pattern.observer.observer.Observer;public class ChineseTeacher extends Subject {// 所有学生集合(所有观察者集合)private List<Observer> studentList = new ArrayList<Observer>();@Overridepublic void addObserver(Observer observer) {studentList.add(observer);}@Overridepublic void removeObserver(Observer observer) {studentList.remove(observer);}// 通知观察者@Overridepublic void notifyObserver() {for (Observer o : studentList) {// 提醒观察者,做出反应o.update();}}// 设置通知者状态@Overridepublic void setSubjectState(String subjectState) {// 接收状态,并设置super.setSubjectState(subjectState);}// 获取通知者状态@Overridepublic String getSubjectState() {// 获取状态return super.getSubjectState();}}

4.观察者抽象类

设计分析: 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时,通知自己。抽象观察者类可以被多个具体观察者继承。

package com.pattern.observer.observer;import com.pattern.observer.subject.Subject;public abstract class Observer {protected String name;protected Subject subject;public Observer(String name, Subject subject) {super();this.name = name;this.subject = subject;}public abstract void update();
}

5.学生观察者类(具体观察者类)

①:打瞌睡的学生观察者类

package com.pattern.observer.observer;import com.pattern.observer.subject.Subject;/*** 瞌睡的学生(具体观察者类)*/
public class SleepStudent extends Observer {// 构造方法public SleepStudent(String name, Subject subject) {super(name, subject);}// 观察者做出反应@Overridepublic void update() {System.out.println(subject.getSubjectState() + "!" + name + ",下雨了,别睡了");}}

②抄作业的学生观察者类:

package com.pattern.observer.observer;import com.pattern.observer.subject.Subject;/*** 抄作业的学生(具体的观察者类)* */
public class CopyHomeworkStudent extends Observer {// 构造方法public CopyHomeworkStudent(String name, Subject subject) {super(name, subject);}// 观察者做出反应@Overridepublic void update() {System.out.println(subject.getSubjectState() + "!" + name + ",高数能考及格了,就别抄数学作业了");}}

5.客户端中使用:

设计分析: 客户端需要依赖指挥着类和具体的建造者类,通过指挥者中的方法,控制建造者绘制具体的人物画像,使得建造者类中的代码和客户端的表示层代码分离,降低耦合度。

注:本客户端用到JavaSwing绘图,若不了解如何用Java绘图,请点击参考本人另一篇博文介绍《 Java用JFrame、JPanel、Graphics绘图案例讲解》。

package com.pattern.observer.client;import com.pattern.observer.observer.CopyHomeworkStudent;
import com.pattern.observer.observer.SleepStudent;
import com.pattern.observer.subject.ChineseTeacher;/*** 客户端类*/
public class Client {public static void main(String[] args) {// 实例化通知者ChineseTeacher chTeacher = new ChineseTeacher();// 实例化观察者SleepStudent sleepStudent = new SleepStudent("王臣", chTeacher);CopyHomeworkStudent copyStudent = new CopyHomeworkStudent("田壮", chTeacher);// 通知者添加被通知对象chTeacher.addObserver(sleepStudent);chTeacher.addObserver(copyStudent);// 通知者改变状态chTeacher.setSubjectState("我要找几个同学爬黑板");// 发出通知chTeacher.notifyObserver();}
}

6.运行结果展示:

我要找几个同学爬黑板!王臣,下雨了,别睡了
我要找几个同学爬黑板!田壮,高数能考及格了,就别抄数学作业了

7.源码下载

本文示例代码下载地址:点击下载

三.总结:

1.观察者模式的优点:

  • 观察者对象和主题对象之间是接触耦合的,二者都依赖于各自的抽象,体现出依赖倒转原则的应用。
  • 建立了一套触发机制,可以当一个对象改变时,同时改变其他对象(类似Oracle的触发器)。

2.观察者式的缺点:

  • 观察者只能知道主题对象发生变化的状态,却不能知道主题对象是怎么发生变化的。
  • 耗时增加,当有很多观察者时,通知所有的观察者会花费很多时间。

设计模式之观察者模式 1相关推荐

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

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

  2. java 观察者模式_图解Java设计模式之观察者模式

    图解Java设计模式之观察者模式 天气预报项目需求 天气预报设计方案 1 - 普通方案 观察者模式(Observer)原理 观察者模式解决天气预报需求 观察者模式在JDK应用的源码分析 天气预报项目需 ...

  3. 游戏服务器架构-设计模式之观察者模式和发布订阅模式真的一样吗?

    前面我给大家分享了观察者模式和发布订阅模式,有人私信给我说这俩不是一样嘛,大体没什么区别,我猜测大多数认为这两者是一样的可以继续阅读这两篇文章,如果还不能解答你的问题,我相信这篇文章对比两者的关系会让 ...

  4. java设计模式观察者模式吗_Java设计模式之观察者模式原理与用法详解

    Java设计模式之观察者模式原理与用法详解 本文实例讲述了Java设计模式之观察者模式原理与用法.分享给大家供大家参考,具体如下: 什么是观察者模式 可以这么理解: 观察者模式定义了一种一对多的依赖关 ...

  5. 设计模式 C++观察者模式

    无论是在现实世界中还是在软件系统中,人们常常会遇到这样一类问题,一个对象的状态改变会引发其他对象的状态改变,如十字路口的交通信号灯,红灯亮则汽车停,绿灯亮则汽车行,再如点击软件中一个按钮,则会弹出一个 ...

  6. 学习《图说设计模式》观察者模式

    图说设计模式之观察者模式 1. 模式动机 建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应.在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一 ...

  7. 设计模式之观察者模式——猫抓老鼠2

    设计模式之观察者模式--猫抓老鼠2: 对猫抓老鼠1再次进行优化,降低代码复杂性,以及使用事件来对方法进行保护 代码优化: 将老鼠代码进行优化,将自己的方法在构造时便注册到猫里面: using Syst ...

  8. 设计模式之观察者模式——猫抓老鼠1

    设计模式之观察者模式--猫抓老鼠: 问题描述: 通过猫抓老鼠的例子进行了解观察者模式,首先的初始代码为(有三个类): using System;/// <summary> /// 观察者设 ...

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

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

  10. 「设计模式(二) - 观察者模式」

    「设计模式(二) - 观察者模式」 一.回复TD退订 日常生活中,这种短信无处不在,各种广告,在互联网高速发展的今天,个人信息可以说是透明的.没有任何隐私可言,类似这种通知其实跟我们开发过程使用的观察 ...

最新文章

  1. SQL基础整理(事务)
  2. 织梦 详情页 php,织梦DEDECMS列表页与详情页调用图集多张图片的方法
  3. docker安装的PHPFPM容器Redis扩展
  4. Linux的基本命令符
  5. (转)Hibernate关联映射——一对多(多对一)
  6. CCF201412-1 门禁系统(100分)
  7. 济南python工资一般多少-济南Go全栈区块链课程
  8. Android -- Camera.ShutterCallback
  9. XML揭秘 入门 应用 精通pdf
  10. Gitlab的管理使用手册
  11. Atitit custom popup 弹窗 techweo layers目录Custom div 1Open 2关闭popup 3关闭事件 3Custom div<!-- pw
  12. [Linux] linux命令总结之dig命令
  13. 软考中级网络工程师全面学习笔记第1版(近4万字)
  14. java毕业设计医院管理系统Mybatis+系统+数据库+调试部署
  15. 一句话理解cmp_to_key函数
  16. 吃不惯的川味麻辣×××
  17. Linux系统下制作windows系统安装U盘
  18. 闲聊机器人实例四:python实现小姜机器人(检索式chatbot_sentence_vec_by_bert_bert句向量)
  19. 性能猛兽野火STM32H743 V2开发板跑Linux 5.10,分数爆炸1836.884644
  20. MACOS 12以上系统如何安装HP打印机驱动

热门文章

  1. 交互技术前沿学习分享-翻译
  2. 经历过黑暗才更渴望黎明_黑暗的图案,你如何操纵以给予更多
  3. UltraDefrag(磁盘碎片整理工具) v8.0.1中文绿色便携版
  4. 怎么用matlab画误差椭圆,matlab画误差椭圆
  5. Java手机游戏开发简明教程 (SunJava开发者认证程序员 郎锐)
  6. C#textBox控件保留上次输入
  7. vue put 提交 400 Bad Request(有时候可以提交成功)
  8. 微信小程序-提交表单成功弹窗提示
  9. Redis升级到 6.x 版本后,12306网站起飞了!
  10. 根据图片名字获取Drawable对象