1.什么是观察者模式
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息
1.1观察者模式应用场景
Zookeeper事件通知节点、消息订阅通知、安卓开发事件注册、分布式配置中心
1.2观察者模式原理类图
抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
2.观察者模式简单的实现
2.1抽象观察者
public interface ObServer {
/**
* 更新消息内容
*
* @param message
* @return
*/
void update(String message);
}
2.2抽象主题者
public abstract class AbstractSubject {
/**
* 添加obServer 该方法将会将观察者注册到主题中
*
* @param obServer
*/
public abstract void addObServer(ObServer obServer);
/**
* 移除obServer 该方法将会把观察者移出主题
*
* @param obServer
*/
public abstract void removeObServer(ObServer obServer);
/**
* 通知所有的notifyObServerAll
*
* @param message
*/
public abstract void notifyObServerAll(String message);
/**
* 设置更新内容
*/
public abstract void setNotifyMessage(String message);
}
2.3具体主题
public class WeChatSubject extends AbstractSubject {
/**
* 观察者集合
*/
public List<ObServer> obServers = new ArrayList<>();
@Override
public void addObServer(ObServer obServer) {
synchronized (this) {
obServers.add(obServer);
}
}
@Override
public void removeObServer(ObServer obServer) {
synchronized (this) {
obServers.remove(obServer);
}
}
@Override
public void notifyObServerAll(String message) {
for (int i = 0; i < obServers.size(); i++) {
ObServer obServer = obServers.get(i);
obServer.update(message);
}
}
@Override
public void setNotifyMessage(String message) {
System.out.println("微信公众号设置message:" + message);
notifyObServerAll(message);
}
}
2.4具体观察者
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 + "接收到微信消息微信消息为:" + message);
}
}
2.5运行测试
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("我们拒绝996");
}
}
3.JDK自带观察实现消息发送
(1). Observable类追踪所有的观察者,并通知他们。
(2). Observer这个接口看起来很熟悉,它和我们之前写的类几乎一样。
3.1自定义主题
public class MessageObServable extends Observable {
@Override
public void notifyObservers(Object arg) {
// 1.改变数据
setChanged();
// 2.通知所有的观察者改变
super.notifyObservers(arg);
}
}
3.2自定义观察者
public class EmailObServer implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("发送邮件内容:" + arg);
}
}
public class SmsObServer implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("发送短信内容:" + arg);
}
}
3.3运行监听开始
public class JdkObServer {
public static void main(String[] args) {
//1.创建主题
MessageObServable messageObServable = new MessageObServable();
// 2.添加订阅者
messageObServable.addObserver(new EmailObServer());
messageObServable.addObserver(new SmsObServer());
// 3.组装消息内容
JSONObject jsonObject = new JSONObject();
jsonObject.put("email", "1234@qq.com");
jsonObject.put("phone", "123456789");
jsonObject.put("text", "消息发送啦");
messageObServable.notifyObservers(jsonObject.toJSONString());
}
}
4.Spring封装事件监听
Spring实现事件通知,底层才观察者模式封装的
public class OrderCreateEvent extends ApplicationEvent {
private JSONObject jsonObject;
public OrderCreateEvent(Object source, JSONObject jsonObject) {
super(source);
this.jsonObject = jsonObject;
}
public JSONObject getJsonObject() {
return jsonObject;
}
public void setJsonObject(JSONObject jsonObject) {
this.jsonObject = jsonObject;
}
}
@Component
public class EmailListener implements ApplicationListener<OrderCreateEvent> {
@Override
@Async
public void onApplicationEvent(OrderCreateEvent event) {
System.out.println(Thread.currentThread().getName() + "发送邮件内容:" + event.getJsonObject().toJSONString());
}
}
@Component
public class SmsListener implements ApplicationListener<OrderCreateEvent> {
@Override
@Async
public void onApplicationEvent(OrderCreateEvent event) {
System.out.println(Thread.currentThread().getName() + "发送短信内容:" + event.getJsonObject().toJSONString());
}
}