这里写目录标题
一、什么是观察者模式
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。
二、观察者模式应用场景
Zookeeper事件通知节点、消息订阅通知、安卓开发事件注册
分布式配置中心
三、观察者模式原理类图
四、观察者模式简单的实现(模拟微信公众号)
公司服务号
两个订阅者:小王、小超
1. 抽象观察者
package com.demo.observer;
public interface ObServer {
/**
* 更新消息内容
* @param message
*/
void update(String message);
}
2. 抽象主题者
package com.demo.observer;
public interface AbstractSubject {
/**
* 添加obServer
* @param obServer
*/
void addObserver(ObServer obServer);
/**
* 移除obServer
* @param obServer
*/
void removeObServer(ObServer obServer);
/**
* 通知所有的notifyObServerAll
* @param message
*/
void notifyObserverAll(String message);
/**
* 设置更新内容
* @param message
*/
void setNotifyMessage(String message);
}
3. 具体主题
package com.demo.observer.impl;
import com.demo.observer.AbstractSubject;
import com.demo.observer.ObServer;
import java.util.ArrayList;
import java.util.List;
public class WeChatSubject implements AbstractSubject {
/**
* 存放所有的ObServer
*/
private List<ObServer> listObServer = new ArrayList<>();
/**
* 更新的内容
*/
private String message;
@Override
public void addObserver(ObServer obServer) {
listObServer.add(obServer);
}
@Override
public void removeObServer(ObServer obServer) {
listObServer.remove(obServer);
}
@Override
public void notifyObserverAll(String message) {
for (int i = 0; i < listObServer.size(); i++) {
ObServer obServer = listObServer.get(i);
obServer.update(message);
}
}
@Override
public void setNotifyMessage(String message) {
this.message = message;
System.out.println("微信公众号设置message:" + message);
notifyObserverAll(message);
}
}
4. 具体观察者
package com.demo.observer.impl;
import com.demo.observer.ObServer;
public class UserObServer implements ObServer {
/**
* 订阅者用户名称
*/
private String name;
/**
* 发送内容
*/
private String message;
public UserObServer(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + ",收到推送消息:" + message);
}
}
5. 运行测试
package com.demo.observer;
import com.demo.observer.impl.UserObServer;
import com.demo.observer.impl.WeChatSubject;
public class Test {
public static void main(String[] args) {
// 1.注册主体
AbstractSubject weChatSubject = new WeChatSubject();
// 2.添加观察者 订阅主题
weChatSubject.addObserver(new UserObServer("小王"));
weChatSubject.addObserver(new UserObServer("小超"));
// 3.设置发送消息
weChatSubject.setNotifyMessage("小王今晚要通宵加班");
}
}
五、JDK自带观察实现消息发送
(1). Observable类追踪所有的观察者,并通知他们。
(2). Observer这个接口看起来很熟悉,它和我们之前写的类几乎一样。
1. 自定义主题
package com.demo.observable;
import java.util.Observable;
public class MessageObServable extends Observable {
@Override
public void notifyObservers(Object arg) {
// 1.修改状态为可以群发
setChanged();
// 2.调用父类的notifyObservers 群发消息
super.notifyObservers(arg);
}
}
2. 自定义观察者
package com.demo.observable.observer;
import java.util.Observable;
import java.util.Observer;
public class SmsObServer implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("用户下单成功,发送短信提醒内容:" + arg);
}
}
package com.demo.observable.observer;
import java.util.Observable;
import java.util.Observer;
public class EmailObServer implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("用户下单成功,发送邮件提醒内容:" + arg);
}
}
package com.demo.observable.observer;
import java.util.Observable;
import java.util.Observer;
public class WechatObServer implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("用户下单成功,发送微信提醒内容:" + arg);
}
}
3. 运行监听开始
package com.demo.observable.observer;
import com.demo.observable.MessageObServable;
import java.util.Observable;
public class TestJdkObserver {
public static void main(String[] args) {
// 1.创建具体的主题
Observable observable = new MessageObServable();
// 2. 注册观察者
observable.addObserver(new SmsObServer());
observable.addObserver(new WechatObServer());
observable.addObserver(new EmailObServer());
// 3. 群发消息
observable.notifyObservers("恭喜您获得平台抽奖机会一次");
/**
* Spring中,项目启动的时候,将这些观察者注册到主题中,调用notifyObservers群发消息
*/
}
}
六、Spring封装事件监听
Maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
package com.demo.event;
import com.alibaba.fastjson.JSONObject;
import org.springframework.context.ApplicationEvent;
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;
}
}
package com.demo.event.listener;
import com.demo.event.OrderMessageEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class EmailListener implements ApplicationListener<OrderMessageEvent> {
@Override
@Async
public void onApplicationEvent(OrderMessageEvent event) {
System.out.println(Thread.currentThread().getName() + "开始发送邮件消息内容:" + event.getJsonObject().toJSONString());
}
}
package com.demo.event.listener;
import com.demo.event.OrderMessageEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class SmsListener implements ApplicationListener<OrderMessageEvent> {
@Override
@Async
public void onApplicationEvent(OrderMessageEvent event) {
System.out.println(Thread.currentThread().getName() + "开始发送短信消息内容:" + event.getJsonObject().toJSONString());
}
}
package com.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.demo.event.OrderMessageEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private ApplicationContext applicationContext;
@RequestMapping("/sendMsg")
public String sendMsg() {
// 1.定义发送消息内容
JSONObject jsonObject = new JSONObject();
jsonObject.put("email", "123456789@163.com");
jsonObject.put("phone", "151123456789");
jsonObject.put("text", "恭喜您以1000元购得iPhone 13 proMax 一部!");
OrderMessageEvent orderMessageEvent = new OrderMessageEvent(this, jsonObject);
applicationContext.publishEvent(orderMessageEvent);
return "success";
}
}
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class AppObServer {
public static void main(String[] args) {
SpringApplication.run(AppObServer.class);
}
}
运行启动类:
访问项目接口:http://127.0.0.1:8080/sendMsg