设计模式系列文章

java设计模式解析(1) Observer观察者模式
java设计模式解析(2) Proxy代理模式
java设计模式解析(3) Factory工厂模式
java设计模式解析(4) Singleton单例模式
java设计模式解析(5) Delegate委派模式
java设计模式解析(6) Strategy策略模式
java设计模式解析(7) Prototype原型模式
java设计模式解析(8) Template模版模式
java设计模式解析(9) Decorator装饰模式
java设计模式解析(10) Adapter适配模式
java设计模式解析(11) Chain责任链模式

主要内容

1、简述

2、实现代码(Talk is cheap,Show me the code)

3、注意点

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)、关系广播链接不能太复杂,否则将难于维护。

 
 
 
 
 
 

最新文章

  1. 深入理解kmp中的next数组
  2. [转]考虑 PHP 5.0~5.6 各版本兼容性的 cURL 文件上传
  3. PCTUSED和PCTFREE对数据操作的影响
  4. matlab中实现Gabor滤波器
  5. NFS配置
  6. source insight 完全卸载和重装
  7. 初学swift笔记 方法(九)
  8. Windows Phone开发(15):资源
  9. margin叠加相邻两个元素的上下margin是叠加在一起
  10. Log4j扩展使用--日志记录器Logger
  11. 老男孩Python全栈开发(92天全)视频教程 自学笔记19
  12. api_response.go
  13. weblogic中部署项目通常有三种方式
  14. ④品茶看&lt;Servlet&amp;JSP&gt;-EL表达式
  15. vue bug &amp; data type bug
  16. Go数据类型和变量
  17. eclipse 编辑代码区字体大小
  18. 任意目录下启动tomcat
  19. ActiveMQ 中的链表
  20. LightOJ - 1030 期望+dp

热门文章

  1. [Python]MySQLdb for Python使用指南/Python的数据库操作
  2. iptables 深度详解
  3. qt creator的使用总结
  4. 爬虫请求库之selenium
  5. Jmeter_数据库
  6. (二) Windows 进行 Docker CE 安装(Docker Desktop)
  7. python day 9: xlm模块,configparser模块,shutil模块,subprocess模块,logging模块,迭代器与生成器,反射
  8. Spring 历史漏洞复现
  9. netaddr网络地址工具python
  10. RedHat 6.3安装MySQL-server-5.6.13-1.el6.x86_64.rpm