Java中常用的设计模式之观察者模式详解
作者:Asurplus、 发布时间:2023-07-27 12:32:52
标签:Java,设计模式,观察者模式
优点
1.观察者和被观察者是抽象耦合的。
2.建立一套触发机制。
缺点
1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2.如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3.观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
注意事项
1.JAVA 中已经有了对观察者模式的支持类。
2.避免循环引用。
3.如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
一、实现方式
1、观察者抽象类
package com.asurplus.common.observe;
/**
* 观察者
*/
public abstract class Observer {
protected Subject subject;
/**
* 发布事件
*/
public abstract void update();
}
2、第一个观察者
package com.asurplus.common.observe;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Observer1 extends Observer {
public Observer1(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
log.info("观察者 1 收到通知:{}", this.subject.getState());
}
}
3、第二个观察者
package com.asurplus.common.observe;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Observer2 extends Observer {
public Observer2(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
log.info("观察者 2 收到通知:{}", this.subject.getState());
}
}
4、第三个观察者
package com.asurplus.common.observe;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Observer3 extends Observer {
public Observer3(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
log.info("观察者 3 收到通知:{}", this.subject.getState());
}
}
5、定义主题
package com.asurplus.common.observe;
import java.util.ArrayList;
import java.util.List;
/**
* 主题
*/
public class Subject {
/**
* 观察者列表
*/
private List<Observer> observers = new ArrayList<>();
/**
* 标志
*/
private int state;
public int getState() {
return state;
}
/**
* 标识被改变
*
* @param state
*/
public void setState(int state) {
this.state = state;
// 通知所有观察者
notifyAllObservers();
}
/**
* 添加进接收者列表
*
* @param observer
*/
public void attach(Observer observer) {
observers.add(observer);
}
/**
* 通知所有人被改变
*/
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
类似于消息发布一样,有多个接收者,当标志位被改变的时候,通知多个接收者。
二、测试
package com.asurplus.common.observe;
public class TestMain {
public static void main(String[] args) {
// 创建主题
Subject subject = new Subject();
// 添加观察者
new Observer1(subject);
new Observer2(subject);
new Observer3(subject);
// 改变标志
subject.setState(10);
}
}
输出结果
可以看出,三个接收者都收到了事件通知,从而实现了我们的观察者模式。
来源:https://lizhou.blog.csdn.net/article/details/123151882


猜你喜欢
- 第1部分 HashSet介绍HashSet 简介HashSet 是一个没有重复元素的集合。它是由HashMap实现的,不保证元素的顺序,而且
- ClassLoader概念我们知道,Java源文件(.java)经过编译器编译之后,会转换成Java字节码(.class),然而程序是如何加
- 简单几步,实现SpringMVC+servlet3.0文件上传功能:第一步:配置web.xml文件中的servlet,添加multipart
- 网上的解决方法:这个是从网上看来的file-->setting-->plugins,搜索tomcat然后install之后会提示
- 实例如下:XSSFilter.javapublic void doFilter(ServletRequest servletrequest,
- 前言在mybatis和mybatis plus里,如果你的实体字段是一个枚举类型,而在数据表里是整型,这时在存储时需要进行处理,默认情况下,
- 最近要做动态数据的提交处理,即需要分析提交数据字段定义信息后才能明确对应的具体字段类型,进而做数据类型转换和字段有效性校验,然后做业务处理后
- 在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的。例如星期一到星期日七个数据元素组成了一
- @CompentScan excludeFilters配置无效@CompentScan 注解配置需要扫描的包excludeFilters 是
- WPF 实现调用 ffmpeg 实现屏幕录制框架使用.NET4Visual Studio 2022需要去 ffmpeg[2]&nb
- 前言本篇开始讲解音频编辑的具体操作,从相对简单的音频裁剪开始。要进行音频裁剪,我的方案是开启一个Service服务用于音频裁剪的耗时操作,主
- Android 仿今日头条评论时键盘自动弹出的效果:当点击评论时,弹出对话框,同时弹出软键盘,当点击返回键时,将对话框关闭,不只是关闭软键盘
- 在Android中偶尔会用到开关,Switch就是一个简单易使用的不错的控件。首先,在布局中添加上Switch控件:<Switch &
- 本文研究的主要是Spring的事务机制的相关内容,具体如下。JAVA EE传统事务机制通常有两种事务策略:全局事务和局部事务。全局事务可以跨
- for循环和foreach循环其实可以算得上是从属关系的,即foreach循环是可以转化成for循环,但是for循环不一定能转换成forea
- 本文简要分析了C#的回调机制。分享给大家供大家参考。具体分析如下:1.回调听起来高大上,实际上本质就是委托,回调是委托的一种应用,其本质就是
- Java synchronized 关键字 可以将一个代码块或一个方法标记为同步代码块。同步代码块是指同一时间只能有一个线程执行的代码,并且
- 前言从windows窗口的概念开始,通过对比去理解Android窗口体系,本文没有深入源码,重在理解概念代码都是抄来抄去,概念也是互相借鉴
- 使用WebSocketSharp自定义实现Web服务时,无法解析multipart/form-data请求的数据。通过查找资料,采用以下方式
- 对于简单的场景来讲,在MEF中导入依赖模块非常简单,只要用ImportAttribute标记依赖的成员,MEF模块会自动找到并创建该模块。但