当前位置: 首页 > news >正文

行为型-观察者模式

文章目录

  • 基本概念
    • 定义
    • 使用场景
    • 代码实现
  • 延伸阅读
    • java监听机制
    • spring监听机制

基本概念

定义

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。
观察者模式包含以下几个核心角色:
主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。
观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。
具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。
观察者模式通过将主题和观察者解耦,实现了对象之间的松耦合。当主题的状态发生改变时,所有依赖于它的观察者都会收到通知并进行相应的更新。

使用场景

一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。通过这种事件触发的机制,将观察者和被观察者进行解耦。
注意事项:
1、JAVA 中已经有了对观察者模式的支持类。(Java中EventObject、EventListener)
2、避免循环引用。
3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

代码实现

主题接口

/*** 抽象主题(抽象被观察者角色)*/
public interface Subject {/*** 所有抽象观察者角色的集合*/List<Observer> observerList = Lists.newArrayList();/*** 注册观察者* @param observer*/default void addObserver(Observer observer){observerList.add(observer);}/*** 取消注册* @param observer*/default void removeObserver(Observer observer){observerList.remove(observer);}/*** 通知所有观察者* @param content*/default void notifyAllObserver(String content){for (Observer observer: observerList){observer.recvMsg(content);}}}

观察者接口

/*** 观察者*/
public interface Observer {void recvMsg(String content);
}

具体被观察者

@Data
public class ConcreteSubject implements Subject<Observer> {private String msg;/*** 发送通知*/public void sendMsg(){System.out.println("ConcreteSubject send msg: " + this.msg);notifyAllObserver(msg);}
}

具体观察者

public class ConcreteObserver implements Observer {@Overridepublic void recvMsg(String content) {System.out.println("ConcreteObserver recv msg:" + content);}
}

测试

public class ObserverTest {public static void main(String[] args) {ConcreteSubject concreteSubject = new ConcreteSubject();concreteSubject.setMsg("important msg");concreteSubject.addObserver(new ConcreteObserver());concreteSubject.sendMsg();}
}

延伸阅读

java监听机制

一、创建事件对象

public class MusicEvent extends EventObject {public static final int STATE_OPEN = 1;public static final int STATE_CLOSE = -1;/*** 状态*/private int state;/*** Constructs a prototypical Event.** @param source the object on which the Event initially occurred* @throws IllegalArgumentException if source is null*/public MusicEvent(Object source) {super(source);}public MusicEvent(Object source, int state) {super(source);this.state = state;}public int getState() {return state;}public void setState(int state) {this.state = state;}
}

二、创建监听器

public interface MusicListener extends EventListener {void play(MusicEvent musicEvent);
}

CloseMusicListener实现

public class CloseMusicListener implements MusicListener{@Overridepublic void play(MusicEvent musicEvent) {if(musicEvent.getState() == MusicEvent.STATE_CLOSE){System.out.println("CloseMusicListener play: stop dance");}}
}

OpenMusicListener实现

public class OpenMusicListener implements MusicListener{@Overridepublic void play(MusicEvent musicEvent) {if(musicEvent.getState() == MusicEvent.STATE_OPEN){System.out.println("OpenMusicListener play: let us go dancing!");}}
}

三、定义事件源,管理监听器

public class EventSource {// 监听器列表,监听器注册入此列表public List<MusicListener> musicListenerList = new ArrayList<>();// 注册监听器public void addMusicListener(MusicListener musicListener) {musicListenerList.add(musicListener);}// 取消注册public void removeMusicListener(MusicListener musicListener) {musicListenerList.remove(musicListener);}// 接收外部事件public void notifyMusicListener(MusicEvent musicEvent) {for (MusicListener musicListener : musicListenerList){musicListener.play(musicEvent);}}
}

四、测试

public class MusicEventTest {public static void main(String[] args) {EventSource eventSource = new EventSource();eventSource.addMusicListener(new OpenMusicListener());eventSource.addMusicListener(new CloseMusicListener());eventSource.notifyMusicListener(new MusicEvent("开门事件", MusicEvent.STATE_OPEN));}
}

spring监听机制

一、创建事件对象,继承ApplicationEvent

@EqualsAndHashCode(callSuper = true)
public class MyEvent extends ApplicationEvent {private String context;public MyEvent(Object source) {super(source);}public String getContext() {return context;}public void setContext(String context) {this.context = context;}
}

二、定义监听器,实现ApplicationListener
MyApplication1

public class MyApplication1 implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent myEvent) {System.out.println("MyApplication1 event:" + myEvent.getContext());}
}

MyApplication2

public class MyApplication2 implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent myEvent) {System.out.println("MyApplication2 event:" + myEvent.getContext());}
}

三、事件通知

@Service
public class MyListenerService {@Autowiredprivate ApplicationEventPublisher applicationEventPublisher;public void register(MyEvent event){applicationEventPublisher.publishEvent(event);}
}

相关文章:

  • php常用设计模式应用场景及示例
  • 超实用!免费软件站大盘点,总有一款适合你
  • 【兆易创新GD32H759I-EVAL开发板】 TLI(TFT LCD Interface)用法详细介绍
  • MySQL调优之SQL语句
  • 从历年315曝光案例,看APP隐私合规安全
  • el-form 的表单校验,如何验证某一项或者多项;validateField 的使用
  • 面试经典-34-验证回文串
  • Github主页设置贪吃蛇详细教程
  • 对AQS的理解
  • coingecko获取token price --php版
  • PTA模拟+数学分析
  • Linux中的文件类型
  • 分享常用的62 个九宫格抽奖及各种宫格效果源码
  • 【Linux】Centos7上安装MySQL5.7
  • phpstudy自定义安装mysql8.3并启动
  • JavaScript-如何实现克隆(clone)函数
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • const let
  • github指令
  • Git初体验
  • socket.io+express实现聊天室的思考(三)
  • Spring Cloud Feign的两种使用姿势
  • Sublime text 3 3103 注册码
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 分享一份非常强势的Android面试题
  • 好的网址,关于.net 4.0 ,vs 2010
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 聊聊hikari连接池的leakDetectionThreshold
  • 前端路由实现-history
  • const的用法,特别是用在函数前面与后面的区别
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # 达梦数据库知识点
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (一)Linux+Windows下安装ffmpeg
  • (原創) 物件導向與老子思想 (OO)
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)创业家杂志:UCWEB天使第一步
  • (转载)Linux 多线程条件变量同步
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .NET CLR基本术语
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .Net MVC4 上传大文件,并保存表单
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .net解析传过来的xml_DOM4J解析XML文件
  • .net开发引用程序集提示没有强名称的解决办法
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • @KafkaListener注解详解(一)| 常用参数详解
  • [.net]官方水晶报表的使用以演示下载
  • [2010-8-30]
  • [30期] 我的学习方法
  • [Angular] 笔记 9:list/detail 页面以及@Output