设计模式系列文章 |
java设计模式解析(1) Observer观察者模式 |
主要内容 |
2、实现代码(Talk is cheap,Show me the code)
1、简述
观察者设计模式在日常软件开发非常常见。比如MQ消息监听、ZooKeeper监听节点事件、Spring发布事件以完成容器初始化(后续会有分析)等。
度娘上对观察者模式有很多版本定义,个人觉得还是《设计模式之禅》定义比较全面,不愧设计模式宝典啊。先贴出来具体定义:
针对上面给出的几个关键对角色,补充一下自己的理解:
1)、Subject:被观察者,即事件的起源。一般在软件实现阶段是 接口 或者 抽象类
2)、Observer:观察者,即观察到事件发生则同步更新自身的状态。一般在软件实现阶段是 接口 或者 抽象类
2、实现代码(Talk is cheap,Show me the code)
《设计模式之禅》已经给出具体的代码实现部分,但是个人觉得过于标准化,现实软件落地肯定会对其进行改造,例如Spring发布事件机制(后续会有分析)。这里个人实现场景,欢迎拍砖:
定义:大学每个学期都会提前订阅该学期的课程,一个课程会被N多个学生订阅。假设某个数学课程任课老师变更之后,学生需要同步更新课程信息,实现自级联变更。
分析:此时可以看出来【课程】就是被观察者的角色,【学生】就是观察者的角色。当【课程】有变动即任课老师变更,需要及时通知【学生】。
Subject课程
/**
* 课程 被观察的对象
* @author zhou.guangfeng on 2019/8/21 下午5:29
*/
public interface Subject {
void teacherChange(String teacherName) ;
}
Student学生
/**
* 学生 观察者
* @author zhou.guangfeng on 2019/8/21 下午5:29
*/
public interface Student {
void changeSubjectTeacherName(String teacherName) ;
}
Observer监听 串联观察者 和 被观察者,同时实现被观察者接口
/**
* 监听 串联观察者 和 被观察者。同时实现被观察者接口
* @author zhou.guangfeng on 2019/8/21 下午5:29
*/
public class Observer implements Subject { private Subject subject ; private List<Student> studentList = new ArrayList<>() ; public Observer(Subject subject) {
this.subject = subject;
} @Override
public void teacherChange(String teacherName) {
subject.teacherChange(teacherName);
studentList.forEach(student -> student.changeSubjectTeacherName(teacherName));
} /**
* 动态注册观察者
*
* @param
* @return
*/
public void registerStudent(Student student){
System.out.println("动态注册观察者 --> " + student);
studentList.add(student) ;
} /**
* 动态删除观察者
*
* @param
* @return
*/
public void removeStudent(Student student){
System.out.println("动态删除观察者 --> " + student);
studentList.remove(student) ;
} }
ObserverMain执行代码
public class ObserverMain { public static void main(String[] args) {
// 被观察者 数学课程
Subject shuxue = new Subject() {
@Override
public void teacherChange(String teacherName) {
System.out.println("数学课程 修改老师为 " + teacherName);
}
}; // 监听者 代理了被观察者 即 数学课程
Observer watcher = new Observer(shuxue) ;
Student student = new Student() {
@Override
public void changeSubjectTeacherName(String teacherName) {
System.out.println("学生A 修改老师为 " + teacherName);
}
} ; // 注册 观察者
watcher.registerStudent(student);
watcher.registerStudent(new Student() {
@Override
public void changeSubjectTeacherName(String teacherName) {
System.out.println("学生B 修改老师为 " + teacherName);
}
}); // 改变课程
watcher.teacherChange("华罗庚"); // 删除监听学生
watcher.removeStudent(student); // 改变课程
watcher.teacherChange("爱因斯坦");
}
}
执行结果:
动态注册观察者 --> com.nancy.observer.ObserverMain$2@6f94fa3e
动态注册观察者 --> com.nancy.observer.ObserverMain$3@5e481248
数学课程 修改老师为 华罗庚
学生A 修改老师为 华罗庚
学生B 修改老师为 华罗庚
动态删除观察者 --> com.nancy.observer.ObserverMain$2@6f94fa3e
数学课程 修改老师为 爱因斯坦
学生B 修改老师为 爱因斯坦
3、注意点
(1)、由于触发观察者是顺序调用,如果观察者很多(例子中student群体特别多,触发时间很长)势必会有效率瓶颈,此时可以考虑使用线程池等异步进行。
(2)、关系广播链接不能太复杂,否则将难于维护。
java设计模式解析(1) Observer观察者模式的更多相关文章
-
java设计模式解析(11) Chain责任链模式
设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析(4) ...
-
Java设计模式(20)观察者模式(Observer模式)
Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...
-
java设计模式(六)--观察者模式
转载:设计模式(中文-文字版) 目录: 简单目标任务实现 观察者模式介绍 观察者模式代码实现 观察者模式是JDK中使用最多的模式之一,非常有用.我们也会一并介绍一对多关系,以及松耦合(对,没错,我们说 ...
-
设计模式18:Observer 观察者模式(行为型模式)
Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...
-
Java设计模式学习笔记(观察者模式)
观察者模式说起来很简单,就是一个订报纸的模式.但是实际上这部分我觉得还是很有意思的,<Head First设计模式>里还有一些还没看完,也是因为理解的不够深吧. 观察者模式会包含两个组件: ...
-
Java设计模式模式观测(Observer Pattern)
Observer Pattern 设计模式通常用于.这是一个事件侦听器模型. 该模型有两个作用,一个是Subject, 有一个Observer.Subject 保存多个Observer参考,一旦一个特 ...
-
【设计模式】java设计模式总述及观察者模式
今天在准备腾讯的面试时想起来要复习一下设计模式,而刚好前几天在参加网易的在线考试的时候,也出了一道关于设计模式的选择题,主要是考察观察者模式,虽然那道题自己做对了,但觉得还是应该好好总结一下设计模式的 ...
-
Java设计模式(三)——观察者模式和监听器
为了实现多个模块之间的联动,最好的方法是使用观察者模式.网上介绍的资料也比较多,今天我就从另一个方面谈谈自己对观察者模式的理解.从JDK提供的支持库里,我们能够找到四个对象:Observable.Ob ...
-
Java设计模式(二) 观察者模式
观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新. 1,定义事件源接口 package com.pattern.observer; pub ...
随机推荐
-
[leetCode][012] Two Sum (1)
[题目]: Given an array of integers, find two numbers such that they add up to a specific target number ...
-
ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转载)
原文地址: http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 原文地址: http://www.trinea.cn ...
-
github Top100
nodejs 文件 var restify = require('restify'), moment = require('moment'), fs = require('fs'), yesterda ...
-
金洪林:红邦创衣止于至善_品牌-生活时尚_品牌_YOKA时尚网
金洪林:红邦创衣止于至善_品牌-生活时尚_品牌_YOKA时尚网 金洪林:红邦创衣止于至善
-
iOS 用GDataXMLNode创建和解析XML
原文地址:http://blog.csdn.net/gf771115/article/details/7718403 NSError *error; // NSString *path = [[ ...
-
com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method findUserByUserNo in the service wusc.edu.facade.user.service.PmsUserFacade.
017-04-25 10:55:30,505 INFO [AbstractRegistry.java:302] : [DUBBO] Register: consumer://192.168.1.101 ...
-
使用.net core在Ubuntu构建一个TCP服务器
介绍和背景 TCP编程是网络编程领域最有趣的部分之一.在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信.以前,我在.NET框架本身写了 ...
-
UNIX环境高级编程--第一章 UNIX基础知识
第一章 UNIX基础知识 1.2 UNIX体系结构 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们将这种软件称为内核(kernel),因为 它相对较小,且 ...
-
7.线程id,优先级讲解
1.线程id可以通过Thread对象的getId()方法得到,在线程出了问题,为什么CPU占用这么高的时候,查的时候我们可以在堆栈信息中找到对应线程,然后干掉该线程就好! 2.而线程对象的getNam ...
-
window.location.search的用法 和 地址栏的的javsscript编码与解码
ocation.search是从当前URL的?号开始的字符串 如:http://www.51js.com/viewthread.php?tid=22720 它的search就是?tid=22720 e ...