概述
观察者模式又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种。
它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

简单实现
主题接口和观察者接口
| |
| public interface Subject { |
| |
| void register(Observer observer); |
| |
| void unregister(Observer observer); |
| |
| void notify(); |
| } |
| |
| |
| public interface Observer { |
| |
| void update(); |
| } |
实现类
| |
| public class TeacherComeSubject implements Subject { |
| private List<Observer> observerList = new ArrayList<>(); |
| |
| @Override |
| public void register(Observer observer) { |
| observerList.add(observer); |
| } |
| |
| @Override |
| public void unregister(Observer observer) { |
| observerList.remove(observer); |
| } |
| |
| @Override |
| public void notfiy() { |
| for (Observer observer : observerList) { |
| observer.update(); |
| } |
| } |
| } |
| |
| |
| public class StudentPlayGameObserver implements Observer { |
| @Override |
| public void update() { |
| System.out.println("停止打游戏,马上写作业"); |
| } |
| } |
| |
| public class StudentChatObserver implements Observer { |
| @Override |
| public void update() { |
| System.out.println("停止聊天,马上写作业"); |
| } |
| } |
客户端
| public static void main( String[] args ) { |
| Subject subject = new TeacherComeSubject(); |
| Observer studentChatObserver = new StudentChatObserver(); |
| Observer studentPlayGameObserver = new StudentPlayGameObserver(); |
| |
| subject.register(studentChatObserver); |
| subject.register(studentPlayGameObserver); |
| |
| |
| subject.notfiy(); |
| } |
执行结果:
Google Guava 实现
EventBus是Guava中的事件处理机制,是观察者模式的优雅实现,使用起来也非常的简单。
它主要由三部分组成:事件总线、事件、事件监听
它的缺点是:只能单进程使用,项目异常重启或者退出不保证消息持久化。如果要支持分布式,还是要用MQ。

0. 引入依赖
| <dependencies> |
| <dependency> |
| <groupId>com.google.guava</groupId> |
| <artifactId>guava</artifactId> |
| <version>20.0</version> |
| </dependency> |
| </dependencies> |
1. 事件总线
| |
| public class EventBusCenter{ |
| private static final EventBus eventBus = new EventBus(); |
| |
| |
| |
| |
| |
| |
| public static void register(EventListener eventListener) { |
| eventBus.register(eventListener); |
| } |
| |
| |
| |
| |
| |
| |
| public static void unregister(EventListener eventListener) { |
| eventBus.unregister(eventListener); |
| } |
| |
| |
| |
| |
| |
| |
| public static void post(Event event) { |
| eventBus.post(event); |
| } |
| } |
2. 事件
| |
| public interface Event { |
| String getName(); |
| } |
| |
| |
| |
| |
| public class TeacherComeEvent implements Event { |
| |
| |
| |
| private String name; |
| |
| public TeacherComeEvent(String name) { |
| this.name = name; |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| } |
| |
| |
| |
| |
| public class TeacherLeaveEvent implements Event { |
| private String name; |
| |
| public TeacherLeaveEvent(String name) { |
| this.name = name; |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| } |
3. 事件监听
| |
| public interface EventListener { |
| |
| } |
| |
| |
| public class TeacherEventListener implements EventListener { |
| |
| |
| |
| |
| |
| |
| @Subscribe |
| public void teacherCome(TeacherComeEvent event) { |
| System.out.println(Thread.currentThread() + "-" + event.getName() + ":停止游戏,假装写作业"); |
| } |
| |
| |
| |
| |
| |
| |
| @Subscribe |
| public void teacherLeave(TeacherLeaveEvent event) { |
| System.out.println(Thread.currentThread() + "-" + event.getName() + ":停止写作业,接着玩游戏"); |
| } |
| } |
使用
| |
| EventListener eventListener = new TeacherEventListener(); |
| |
| EventBusCenter.register(eventListener); |
| |
| EventBusCenter.post(new TeacherComeEvent("数学老师来了")); |
| EventBusCenter.post(new TeacherLeaveEvent("数学老师走了")); |
执行结果:
| Thread[main,5,main]-数学老师来了:停止游戏,假装写作业 |
| Thread[main,5,main]-数学老师来了:停止写作业,接着玩游戏 |
异步处理
比如说,事件发生之后,不想立即处理,而是异步处理,只需换一个 EventBus 即可
| |
| |
| |
| private static final EventBus eventBus = new AsyncEventBus(Executors.newCachedThreadPool()); |
观察此时的执行结果:
| Thread[pool-1-thread-1,5,main]-数学老师来了:停止游戏,假装写作业 |
| Thread[pool-1-thread-2,5,main]-数学老师来了:停止写作业,接着玩游戏 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2018-04-04 windows下使用批处理设置环境变量