设计模式-观察者模式
背景
自从有了微信公众号后,关注了某个公众号基本每天都有新的文章推送的通知,我们可以很方便的进行查阅,了解最新的资讯,什么老美放大水、什么中东又暴乱了,第一时间就知道了,而这里的关注和通知的行为其实有点类似观察者模式的观察者。用户关注公众号,公众号(被观察者)更新文章通知所有用户(观察者)。
观察者模式是什么?
观察者模式(Observer Pattern)它属于行为模式。定义了一种一对多依赖的系,使用每当一个对象改变状态,则所有的依赖于它的对象都会得到通知并被自动更新。
角色:
ObServer(观察者):负责监听消息,当收到被观察者的状态改变时通知自己,做出更新动作。
ConcreteObServer(具体观察者):具体实现观察者的实现。
Subject(被观察者):负责将所有的观察者保存在一个集合里,并且支持动态增减。
ConcreteSubject(具体被观察者):具体的被观察者的实现,当内部发生改变时,通知所有的观察者。
观察者模式可以干嘛?
观察者模式主要解决是一对多或者多对多之间依赖通知的问题。通过一个监听的中间件,当被观察者发生改变,去通知所有观察者,以达到观察者与被观察关系解耦,非直接依赖关系,并且双方有利于拓展。
优点:
单一职责:由于观察者、被观察者、的职责单一,所有符合该规则。
开闭原则:支持对新的观察者和被观察者的增加。
低耦合:观察者、被观察者双方都没有直接的联系,而且通过消息的通知进行。
缺点:
效率:在开发上需要开发各个角色的功能,在业务流程上都是通过消息进行通知去触发,如果数据量比较大可能会效率较低。
个人理解:
观察者模式就类似于我们(观察者)订阅(监听)微信公众号(被观察者),微信公众号发布文章通知到我们,我们查阅。
观察者模式类图
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
实现代码
/**
* @Auther: csh
* @Date: 2020/6/11 11:03
* @Description:抽象观察者(ObServer)
*/
public abstract class ObServer {
protected Subject subject;
public abstract void update(String message);
}
/**
* @Auther: csh
* @Date: 2020/6/11 11:04
* @Description:被观查者
*/
public class Subject {
protected List<ObServer> obServerList = new ArrayList <ObServer>();
private String message;
//添加订阅者
public void attach(ObServer obServer){
obServerList.add(obServer);
}
//删除订阅者
public void del(ObServer obServer){
if(null!=obServer){
obServerList.remove(obServer);
}
}
//通知所有订阅者
public void notifyAllObservers(String message){
for (ObServer obServer : obServerList) {
obServer.update(message);
}
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
* @Auther: csh
* @Date: 2020/6/11 11:12
* @Description:用户(具体观察者)
*/
public class User extends ObServer {
private String name;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println("用户:"+name+"收到通知:"+message);
}
}
/**
* @Auther: csh
* @Date: 2020/6/11 11:18
* @Description:观察者模式,用户关注的公众号后,公众号更新文章通知所有用户。
*/
public class Client {
public static void main(String[] args) {
//关注【技术趋势】公众号
Subject jsqs = new Subject();
//用户
User user = new User("小明");
User user2 = new User("小红");
User user3 = new User("小绿");
//订阅公众号
jsqs.attach(user);
jsqs.attach(user2);
jsqs.attach(user3);
//公众号更新文章
jsqs.notifyAllObservers("观察者模式");
}
}
结果
用户:小明收到通知:观察者模式
用户:小红收到通知:观察者模式
用户:小绿收到通知:观察者模式
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
最后
观察者模式主要解决是一对多或者多对多之间依赖通知的问题,在redis订阅、邮件订阅、消息通知等者借鉴该模式的思想,所以该模式应用于实际工作中非常广泛,当然若日常开发遇到,非必须的情况下直接用已成熟的开源框架为多。
开源场景:
java
java.util.Observer
java.util.Observable
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 解析JSON
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 处理静态资源
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 视图Nunjucks
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 代码分层
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ HTTP请求
- ubuntu中安装tomcat
- python文件操作
- Owasp测试4.0手册
- 推荐一款Web渗透测试数据库
- 【提莫】一个域名收集及枚举工具
- chmod: changing permissions of `/usr/local/bin/...
- a windows service with the name MYSQL already e...
- NameError: name 'admin' is not defined(彻底解决方案)
- Error: No module named blog
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【43期】盘点那些必问的数据结构算法题之二叉树基础
- 精讲RestTemplate第8篇-请求失败自动重试机制
- 精讲RestTemplate第7篇-自定义请求失败异常处理
- 精讲RestTemplate第10篇-使用代理作为跳板发送请求
- 精讲响应式WebClient第5篇-请求超时设置与异常处理
- 精讲响应式WebClient第4篇-文件上传与下载
- 【大家的项目】Rust Base62 库学习和分析
- ES2020 中 Javascript 10 个你应该知道的新功能
- Webpack5 跨应用代码共享 - Module Federation
- 【Rust日报】2020-09-16 - Rust 2021 规划
- 精讲响应式WebClient第3篇-POST、DELETE、PUT方法使用
- C++的黑魔法: 用四种方式实现add!
- 精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方法详解
- 算法篇:位运算异或的使用(一)
- 精讲响应式webclient第1篇-响应式非阻塞IO与基础用法