蚂蚁课堂第5期-互联网架构-007:观察者模式
程序员文章站
2022-06-15 11:35:00
...
1 观察者模式应用场景
课程内容:
1、什么是观察者、观察者模式应用场景
2、观察者实现的思路有那些
3、基于Jdk自带观察者模式实现消息异步传输
4、基于SpringBoot项目实现观察者模式
什么是观察者模式
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。
观察者模式应用场景
Zookeeper事件通知节点、消息订阅通知、安卓开发事件注册、分布式配置中心
2 观察者模式类图原理
抽象主题(被观察者):它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。
抽象观察者:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体主题(被观察者):在具体主题的内部状态改变时,向所有注册过的观察者发出通知。
具体观察者:实现抽象观察者角色的更新接口,一边使本身的状态与主题的状态相协调。
3 纯手写Java观察者模式
抽象观察者
public interface Observer {
/**
* 通知观察者消息
* @param message
*/
void update(String message);
}
抽象主题
public interface AbstractSubject {
/**
* 添加观察者 注册观察者
*
* @param observer
*/
void addObserver(Observer observer);
/**
* 移除观察者
*
* @param observer
*/
void removeObserver(Observer observer);
/**
* 通知消息
*
*/
void notifyObserver(String message);
}
具体主题
public class WeChatSubject implements AbstractSubject {
// 如何存放这些主题
private List<Observer> observerList = new ArrayList<>();
@Override
public void addObserver(Observer observer) {
// 注册或添加观察者
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObserver(String message) {
System.out.println("开始设置微信群发消息:" + message);
// 调用观察者通知方法
for (int i = 0; i < observerList.size(); i++) {
Observer observer = observerList.get(i);
// 调用该方法通知 获取具体的消息 群发
observer.update(message);
}
}
}
具体观察者
public class UserObserver implements Observer {
private String name;
public UserObserver(String name){
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "老师收到消息..");
}
}
测试类
public class Test001 {
public static void main(String[] args) {
// 1.创建具体的主题
AbstractSubject abstractSubject = new WeChatSubject();
// 2.开始注册或者添加观察者
abstractSubject.addObserver(new UserObserver("小薇"));
abstractSubject.addObserver(new UserObserver("小敏"));
// 3.群发消息
abstractSubject.notifyObserver("蚂蚁课堂666..");
}
}
运行结果
4 JDK观察者模式源码分析
1.Observer(观察者)
2.Observable(主题)追踪所有的观察者,并通知他们。
5 使用JDK观察者群发消息
自定义主题
public class MessageObservable extends Observable {
@Override
public void notifyObservers(Object arg) {
// 1.修改状态为可以群发
setChanged();
// 2.调用父类的notifyObservers 群发消息
super.notifyObservers(arg);
}
}
自定义观察者
public class SmsObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("用户下单成功,发送短信提醒内容:" + arg);
}
}
public class EmailObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("用户下单成功,发送邮件提醒内容:" + arg);
}
}
public class WechatObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("用户下单成功,发送微信提醒内容:" + arg);
}
}
运行监听开始
public class TestJdkObserver {
public static void main(String[] args) {
// 1.创建具体的主题
Observable observable = new MessageObservable();
// 2.注册观察者
observable.addObserver(new SmsObserver());
observable.addObserver(new EmailObserver());
observable.addObserver(new WechatObserver());
// 3.群发消息
observable.notifyObservers("恭喜您中奖!");
}
}
测试结果:
注意:实际开发中具体观察者中的方法要异步处理,要单独有线程去运行这段代码。
6 SpringBoot事件通知底层原理
Spring封装事件监听
Spring实现事件通知,底层是采用观察者模式封装的
下单消息事件 OrderMessageEvent
public class OrderMessageEvent extends ApplicationEvent {
/**
* 群发消息的内容
*/
private JSONObject jsonObject;
public OrderMessageEvent(Object source, JSONObject jsonObject) {
super(source);
this.jsonObject = jsonObject;
}
public JSONObject getJsonObject() {
return jsonObject;
}
public void setJsonObject(JSONObject jsonObject) {
this.jsonObject = jsonObject;
}
}
事件监听者 EmailListener/SmsListener
@Component
public class EmailListener implements ApplicationListener<OrderMessageEvent> {
@Override
@Async
public void onApplicationEvent(OrderMessageEvent event) {
// 如何获取到当前容器下面所有的观察者? 通过反射机制获取ApplicationListener接口下面的子类
System.out.println(Thread.currentThread().getName() + "开始发送邮件消息内容:" + event.getJsonObject().toString());
}
}
@Component
public class SmsListener implements ApplicationListener<OrderMessageEvent> {
@Override
@Async
public void onApplicationEvent(OrderMessageEvent event) {
System.out.println(Thread.currentThread().getName() + "开始发送短信消息内容:" + event.getJsonObject().toString());
}
}
控制层
@RestController
public class OrderController {
@Autowired
private ApplicationContext applicationContext;
@RequestMapping("/sendMsg")
public String sendMsg() {
// 1.定义发送消息内容
JSONObject jsonObject = new JSONObject();
jsonObject.put("email", "aaa@qq.com");
jsonObject.put("phone", "15123456789");
jsonObject.put("text", "恭喜您中奖!");
OrderMessageEvent orderMessageEvent = new OrderMessageEvent(this, jsonObject);
applicationContext.publishEvent(orderMessageEvent);
return "success";
}
}
启动类
@SpringBootApplication
@EnableAsync
public class AppObserver {
public static void main(String[] args) {
SpringApplication.run(AppObserver.class);
}
}
运行结果: