目录

观察者模式 简述

编码实现

番外版


观察者模式 简述

1、观察者模式又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

2、观察者模式是类和类之间的关系,不涉及到继承。

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

MySubject 类是主对象,Observer1(观察者1)和 Observer2 (观察者1)依赖于 MySubject 的对象,当 MySubject 变化时,Observer1 和 Observer2 必然变化。

AbstractSubject 类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当 MySubject 变化时,负责通知在列表内存在的对象

编码实现

1、下面使用代码实现上图,假如让一个人(Person)作为被观察对象,一只猫(Cat)和一只狗(Dog)作为观察者,当人开始吃饭时,猫和狗就会收到通知,知道它们的主人开始吃饭了。

2、观察者如下:

package com.lct.observerModel;//观察者-设计成接口,所有的实现类都是观察者
public interface Observer {/*** 监控对象发生变化后,此方法用于收到通知,然后自己进行相应的处理** @param message :接收的通知信息,如果需要接收发布者的信息,则可以加上,否则可以取消*/public void update(String message);
}
package com.lct.observerModel;import java.util.logging.Logger;//猫---实现 Observer 后,自己也是观察者
public class Cat implements Observer {@Overridepublic void update(String message) {Logger logger = Logger.getAnonymousLogger();logger.info("汤姆猫:我看到主人准备吃 " + message + " ,我也开始吃猫粮...");}
}
package com.lct.observerModel;import java.util.logging.Logger;//狗---实现 Observer 后,自己也是观察者
public class Dog implements Observer {@Overridepublic void update(String message) {Logger logger = Logger.getAnonymousLogger();logger.info("哮天犬:我看到主人准备吃 " + message + " ,我也开始吃狗粮...");}
}

3、被观察者/发布者如下:

package com.lct.observerModel;//主题---设计成接口,制定规范
// Subject 与 Observer 是两条不同的线,通过 Subject(主题)添加、删除观察者、以及通知观察者等
public interface Subject {public void addObserver(Observer observer);//添加观察者public void delObserver(Observer observer);//剔除观察者/*** 通知所有观察者** @param message :发送给观察者的信息,如果对方不需要接收信息,则可以取消*/public void notifyObservers(String message);/*** 上面是对观察者的操作,下面可以定义监控对象(主题)自身的操作** @param food 食物名称*/public void eat(String food);
}
package com.lct.observerModel;import java.util.Iterator;
import java.util.List;
import java.util.Vector;/*** 主题(被监控对象)抽象类,实现 主题接口* 主要是显得层次更加清晰,所以采用 接口 -> 抽象类 -> 具体类 的结构* 接口中定义所有规范,抽象类中实现所有对观察者的操作,主题具体的操作交由自己的子类去实现*/
public abstract class AbstractSubject implements Subject {private List<Observer> observerVector = new Vector<>();@Overridepublic void addObserver(Observer observer) {observerVector.add(observer);}@Overridepublic void delObserver(Observer observer) {observerVector.remove(observer);}@Overridepublic void notifyObservers(String message) {//通知所有观察者Iterator<Observer> observerIterator = observerVector.iterator();while (observerIterator.hasNext()) {observerIterator.next().update(message);//通知的同时传递信息}}
}
package com.lct.observerModel;import java.util.logging.Logger;//主题具体的实现类,当然还可以有其它类型的子类,都实现自己 eat 方法即可
public class Person extends AbstractSubject {@Overridepublic void eat(String food) {Logger logger = Logger.getAnonymousLogger();/*** 在自己的执行之前通知所有观察者,则观察者先执行* 同理放在自己的执行之后通知所有观察者,则观察者后执行*/notifyObservers(food);//将自己的吃的食物作为信息传递给观察者logger.info("杨戬:本君要开始用膳 " + food);}
}

4、测试如下:

package com.lct.test;import com.lct.observerModel.*;public class Test {public static void main(String[] args) {Observer observer_cat = new Cat();Observer observer_dog = new Dog();Subject subject = new Person();subject.eat("蚂蚁上树");//此时未添加观察者,所以不会有对象收到通知subject.addObserver(observer_cat);subject.eat("辣椒炒肉");//此时 cat 会收到通知subject.addObserver(observer_dog);subject.eat("水煮鱼");//此时 cat 、dog 都会收到通知}
}

番外版

1、这种方法相比上面的方式,比较不容易理解,但也是一种方法

2、观察者设计模式三要素:

事件源:触发事件的对象,需要注册监听器

监听器:一般设计成接口,由使用者来实现其中的它想要监听的方法

事件:触发的事件,里面要封装事件源

3、假设现在要监听学生(Student)小明的学习(study)和睡觉(sleep)情况

事件源

package test.publish;/*** Created by Administrator on 2018/7/20 0020.* 事件源(观察的目标)----下面监听它的study()、 sleep()方法* 需要注册监听器*/
public class Student {/*** name:学生的普通属性* bookName:学习的书名* studentListener:学生监听器*/private String name;private String bookName;private StudentListener studentListener;public void study(String bookName) {this.bookName = bookName;/** 当注册了监听器时,则实施方法监听* 监听器方法中含有事件,事件又封装了事件源,而用户实现了监听器* 所以每次此方法一运行,用户会先监听到,而且能从事件中获取事件源(Student)数据*/if (studentListener != null) {studentListener.studyListener(new StudentEven(this));}System.out.println("我是 " + name + " ,准备学习 " + bookName);}public void sleep() {/** 当注册了监听器时,则实施方法监听,与上同理*/if (studentListener != null) {studentListener.sleepListener(new StudentEven(this));}System.out.println("我是 " + name + " ,准备睡觉!");}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getBookName() {return bookName;}/*** 注册监听器* 只要当注册了监听器,才能监听方法** @param studentListener*/public void addStudentListener(StudentListener studentListener) {this.studentListener = studentListener;}
}

事件

package test.publish;/*** Created by Administrator on 2018/7/20 0020.* 事件---封装事件源,便于事件源对象的传入传出* 这样的好处是以后用户可以通过触发的事件获取事件源,从而可以获取数据源的数据*/
public class StudentEven {private Object evenSource;public StudentEven(Object evenSource) {this.evenSource = evenSource;}public Object getEvenSource() {return evenSource;}public Student getStudent() {return (Student) evenSource;}
}

监听器

package test.publish;/*** Created by Administrator on 2018/7/20 0020.* 监听学生的监听器,通常设计成接口,让用户自己实现* 用户可以从 StudentEven 中获取事件源*/
public interface StudentListener {/*** 监听器监听的方法** @param studentEven 监听器监听的事件*/void studyListener(StudentEven studentEven);void sleepListener(StudentEven studentEven);
}

用户监听

package test.publish;/*** Created by Administrator on 2018/7/20 0020.* 自己实现监听器,这和使用Java Web的监听器道理是一样的* 如果只想监听里面的部分方法,则可以再加适配器*/
public class MyStudentListener implements StudentListener {@Overridepublic void studyListener(StudentEven studentEven) {Student student = studentEven.getStudent();System.out.println("-----------监听到 " + student.getName() + " 开始学习 " + student.getBookName());}@Overridepublic void sleepListener(StudentEven studentEven) {Student student = studentEven.getStudent();System.out.println("-----------监听到 " + student.getName() + " 开始睡觉");}
}

测试结果

/*** Created by Administrator on 2018/7/20 0020.* 未注册监听器时*/
public class MyTest {public static void main(String[] args) {Student student = new Student();student.setName("小明同学");student.study("论语");student.sleep();}
}
//输出如下
//我是 小明同学 ,准备学习 论语
//我是 小明同学 ,准备睡觉!
//Process finished with exit code 0
/*** Created by Administrator on 2018/7/20 0020.* 注册监听后*/
public class MyTest {public static void main(String[] args) {Student student = new Student();student.setName("小明同学");student.addStudentListener(new MyStudentListener());student.study("论语");student.sleep();}
}/*
-----------监听到 小明同学 开始学习 论语我是 小明同学 ,准备学习 论语-----------监听到 小明同学 开始睡觉我是 小明同学 ,准备睡觉!Process finished with exit code 0
*/

Java 设计模式 之 观察者模式(Observer)相关推荐

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

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

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

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

  3. Java设计模式系列--观察者模式(使用)

    原文网址:Java设计模式系列--观察者模式(使用)_IT利刃出鞘的博客-CSDN博客 简介 说明 本文用示例介绍观察者模式的用法. 观察者模式的含义 以微信公众号为例.我们关注了某个微信公众号后能收 ...

  4. Java设计模式之观察者模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  5. java设计模式 观察者模式_理解java设计模式之观察者模式

    在生活实际中,我们经常会遇到关注一个事物数据变化的情况,例如生活中的温度记录仪,当温度变化时,我们观察它温度变化的曲线,温度记录日志等.对于这一类问题,很接近java设计模式里面的"观察者模 ...

  6. Java 设计模式之观察者模式

    一.了解观察者模式 1.1 什么是观察者模式 观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象状态改变时,它的所有依赖者都会收到通知并自动更新. 典型的问题比如报社,只要你是他们的订户,他们 ...

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

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

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

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

  9. (设计模式十三)java设计模式之观察者模式

    特别说明:本篇博客来自于设计模式菜鸟教程 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern).比如,当一个对象被修改时,则会自动通知它的依赖对象.观察者模式属于 ...

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

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

最新文章

  1. MYSQL 5.6安装设置中英文翻译
  2. cesium 3dtiles 加载本地数据_cesium结合geoserver实现地图空间查询(附源码下载)
  3. 从CSRF原理到CMS漏洞利用
  4. 【距离GDOI:128天】【POJ2778】DNA Sequence(AC自动机+矩阵加速)
  5. Keras——Keras简介、安装、backend
  6. android6.0相机权限申请
  7. Mybatis中使用左连接查询
  8. Android email中无法登陆gmail邮箱 M
  9. 炫彩的按钮渐变动画——css3
  10. 哪种锻炼方式最能让程序猿远离亚健康? - 强烈推荐
  11. 如何设置IDEA代码风格为Google风格,使用Google风格format
  12. 在计算机网络中 工作在物理层上的设备,简述工作在物理层,数据链路层和网络层上的设备分别有哪些...
  13. ios safari 描述文件 跳转到_iOS-app跳转safari及从safari跳回app功能实现
  14. 第5章 8051单片机工作原理
  15. matlab中eacf函数,基于MATLAB的切比雪夫I型模拟低通滤波器设计
  16. 2022哈工大软件构造lab1小结(知识点)
  17. 电影评分数据分析python_豆瓣电影简单评分模型-从收集数据到建模分析
  18. 39. 什么是spring通知(Advice)?
  19. Android开发——APP门户界面设计
  20. 记录java.util.Collections.unmodifiableList()使用

热门文章

  1. 【大数据部落】R语言如何使用rjags R2jags来建立贝叶斯模型
  2. 拓端tecdat|R语言离群值处理分析
  3. 杭电1091题c语言答案,杭电题目acm部分答案.doc
  4. pytorch与Keras对应模型Sequential()和add()
  5. 人脸检测-MTCNN算法笔记和代码解读
  6. python之collections模块Counter类使用学习
  7. python excel 教程推荐_python脚本实现数据导出excel格式的简单方法(推荐)
  8. python center用法_【语言学习】python——字符串
  9. linux 程序崩溃 gdb调试coredump文件
  10. FISCO BCOS 跨链WeCross ppt