观察者模式的学习
定义
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。哈哈,定义就是用专业术语介绍专业术语,特别难理解,下面通过一个例子来解析。
观察者模式UML图
Observer
:观察者,在发布订阅中充当订阅者,jdk提供的
Observable
:被观察者,在发布订阅充当发布者,jdk提供的
Subscriber
:订阅者
Publisher
:发布者
public interface Observer {
//对被观察者的变化做出响应的方法
void update(Observable o, Object arg);
}
/**
* @author : zwy
* create at: 2021/5/16 上午10:58
* @description: 订阅者
*/
public class Subscriber implements Observer {
private String name;
public Subscriber(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
//简单的输出
System.out.println(name + "收到消息:" + arg);
}
}
public class Observable {
//是否改变
private boolean changed = false;
//所有的观察者
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
//添加观察者
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
//不存在才添加
if (!obs.contains(o)) {
obs.addElement(o);
}
}
//删除观察者
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
//通知所有观察者
public void notifyObservers() {
notifyObservers(null);
}
//通知所有观察者
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
//是否改变
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
//循环通知所有观察者
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
//清空所有观察者
public synchronized void deleteObservers() {
obs.removeAllElements();
}
//设置改变
protected synchronized void setChanged() {
changed = true;
}
//设置为未改变
protected synchronized void clearChanged() {
changed = false;
}
//判断是否改变
public synchronized boolean hasChanged() {
return changed;
}
//得到所有观察者数量
public synchronized int countObservers() {
return obs.size();
}
}
/**
* @author : zwy
* create at: 2021/5/16 上午11:00
* @description: 发布者
*/
public class Publisher extends Observable {
public void publish(String message){
//设置已经改变
setChanged();
//通知所有观察者
notifyObservers(message);
}
}
/**
* @author : zwy
* create at: 2021/5/16 上午11:03
* @description: 客户端
*/
public class Client {
public static void main(String[] args) {
//发布者
Publisher publisher = new Publisher();
//定义4个订阅者
Subscriber s1,s2,s3,s4;
s1 = new Subscriber("订阅者1");
s2 = new Subscriber("订阅者2");
s3 = new Subscriber("订阅者3");
s4 = new Subscriber("订阅者4");
//添加订阅者
publisher.addObserver(s1);
publisher.addObserver(s2);
publisher.addObserver(s3);
publisher.addObserver(s4);
//发布消息
publisher.publish("hello world");
}
}
输出结果:
订阅者4收到消息:hello world
订阅者3收到消息:hello world
订阅者2收到消息:hello world
订阅者1收到消息:hello world
观察者模式在Spring中的使用
EventObject
:事件对象,JDK提供的,观察者模式中的被观察者
ApplicationEvent
:事件对象,Spring继承EventObject得到的,观察者模式中的被观察者
EventListener
:监听器,JDK提供的,观察者模式中的观察者
ApplicationListener
:监听器,Spring继承EventListener得到的,观察者模式中的观察者
ApplicationEventMulticaster
:事件广播器,用来广播事件的,实现类AbstractApplicationEventMulticaster
、SimpleApplicationEventMulticaster
EmailEvent
:自定义的事件对象
EmailListener
:自定义的监听器
Spring实现的观察者模式和JDK提供的有一点不同,JDK由被观察来通知所有的观察者,Spring多了一个ApplicationEventMulticaster
来进行事件的广播。但是在使用上是差不多的,看如下例子:
/**
* @author : zwy
* create at: 2021/5/16 下午12:25
* @description: 邮件事件
*/
public class EmailEvent extends ApplicationEvent {
private String email;
private String content;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
/**
* Create a new {@code ApplicationEvent}.
*
* @param source the object on which the event initially occurred or with
* which the event is associated (never {@code null})
*/
public EmailEvent(Object source) {
super(source);
}
public EmailEvent(Object source, String email, String content) {
super(source);
this.email = email;
this.content = content;
}
}
/**
* @author : zwy
* create at: 2021/5/16 下午12:32
* @description: 邮件监听器
*/
@Component
public class EmailListener implements ApplicationListener<EmailEvent> {
@Override
public void onApplicationEvent(EmailEvent event) {
System.out.println("邮件监听器监听到邮件地址:" + event.getEmail() + "邮件内容:" + event.getContent());
}
}
/**
* @author : zwy
* create at: 2021/5/16 下午12:39
* @description: 客户端
*/
@SpringBootApplication
public class Client {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Client.class, args);
ApplicationListener emailListener = new EmailListener();
ApplicationListener emailListener2 = new EmailListener();
applicationContext.addApplicationListener(emailListener);
applicationContext.addApplicationListener(emailListener2);
applicationContext.publishEvent(new EmailEvent("","15259070752@163.com","测试邮件监听器!"));
}
}
输出结果:
邮件监听器监听到邮件地址:15258870752@163.com邮件内容:测试邮件监听器!
邮件监听器监听到邮件地址:15258870752@163.com邮件内容:测试邮件监听器!
下面简单看一下Spring中的代码:
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
//事件源
protected transient Object source;
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
//得到事件源
public Object getSource() {
return source;
}
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
public interface EventListener {
}
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
//处理事件响应
void onApplicationEvent(E event);
}
//省略了部分不重要的代码
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(final ApplicationEvent event) {
//getApplicationListeners得到所有的监听器,循环进行通知
for (final ApplicationListener<?> listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
//异步进行
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
//同步进行
invokeListener(listener, event);
}
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
//调用通知方法
listener.onApplicationEvent(event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
//调用通知方法
listener.onApplicationEvent(event);
}
}
}