首页 技术 正文
技术 2022年11月20日
0 收藏 954 点赞 4,112 浏览 3465 个字

概述

观察者模式又被称为发布-订阅(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(); /**
* 登记事件监听
*
* @param eventListener
*/
public static void register(EventListener eventListener) {
eventBus.register(eventListener);
} /**
* 注销登记事件监听
*
* @param eventListener
*/
public static void unregister(EventListener eventListener) {
eventBus.unregister(eventListener);
} /**
* 推送事件
*
* @param 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 { /**
* 监听老师来了事件
*
* @param event
*/
@Subscribe
public void teacherCome(TeacherComeEvent event) {
System.out.println(Thread.currentThread() + "-" + event.getName() + ":停止游戏,假装写作业");
} /**
* 监听老师走了事件
*
* @param event
*/
@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 即可

//修改EventBusCenter
//private static final EventBus eventBus = new EventBus();
//异步处理事件
private static final EventBus eventBus = new AsyncEventBus(Executors.newCachedThreadPool());

观察此时的执行结果:

Thread[pool-1-thread-1,5,main]-数学老师来了:停止游戏,假装写作业
Thread[pool-1-thread-2,5,main]-数学老师来了:停止写作业,接着玩游戏
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,090
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,567
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,415
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,187
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,823
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,906