一、基于java.util.Observable和java.util.Ovbserver的 观察者模式基础实现
1. Observable ——抽象的被观察者
package java.util;
/**
* 源码来自jdk1.0 java.util包
*
* @author Chris Warth
* @since JDK1.0
*/
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
/** Construct an Observable with zero Observers. */
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);
}
/**
* 如果此对象已更改,如<code> hasChanged <code>方法所示,则通知其所有观察者,
* 然后调用<code> clearChanged <code>方法以指示该对象不再更改。
*
* 每个观察者都实现一个update方法,update方法有两个参数,第一个是当前被观察对象,第二个一个是null
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* 如果此对象已更改,如<code> hasChanged <code>方法所示,则通知其所有观察者,
* 然后调用<code> clearChanged <code>方法以指示该对象不再更改。
*
* 每个观察者都实现一个update方法,update方法有两个参数,第一个是当前被观察对象,第二个一个是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();
}
/**
* 将此Observable 对象标记为已更改;hasChanged 方法现在将返回true.
*/
protected synchronized void setChanged() {
changed = true;
}
/**
* 指示此对象不再更改,或者它已经将其最近的更改通知了所有观察者,
* 因此 hasChanged 方法现在将返回false。该方法由<code> notifyObservers <code>方法自动调用。
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* 测试此对象是否已更改。
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* 返回这个的Observable对象的观察者数量。
*/
public synchronized int countObservers() {
return obs.size();
}
}
2. Observer —— 抽象观察者
package java.util;
/**
* 观察者
*
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* 更新自身
* @param o 被观察对象
* @param arg 一般是个null
*/
void update(Observable o, Object arg);
}
接下来我们模拟一个场景,放学铃响了大家会做什么?
3. SchoolBell —— 被观察的实现
/**
* 学校的铃
*
* @author Wilton Jia
* @date 2021/4/26
*/
public class SchoolBell extends Observable {
/**
* 响铃动作
*/
public void ring(){
System.out.println("放学铃响了");
//修改状态
setChanged();
//通知所有观察者
super.notifyObservers();
}
}
4. T <?extends Observer> —— 观察者的实现
/**
* 老师
* @author Wt Jia
* @date 2021/4/26
*/
public class Teachers implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println(" Teacher 开车回家");
}
}
/**
* 学生们
*
* @author Wilton
* @date 2021/4/26
*/
public class Students implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("Student 坐校车回家");
}
}
/**
* 门卫大爷
*
* @author Wilton
* @date 2021/4/26
*/
public class Guard implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("Guard 锁学校门");
}
}
5. ObserverInvoker——调用演示
/**
* 观察者模式的调用
*
* @author Wilton
* @date 2021/4/26
*/
public class ObserverInvoker {
public static void main(String[] args) {
SchoolBell schoolBell = new SchoolBell();
schoolBell.addObserver(new Teachers());
schoolBell.addObserver(new Students());
schoolBell.addObserver(new Guard());
schoolBell.ring();
}
}
二、基于JDK的EventObject和EventListener实现观察者模式
Spring中观察者模式的应用就是基于这两个类,但是区别在于这种方式中EventObject无法自己通知到监听者,需要一个第三方通知所有的监听者。
1. EventObject——抽象的事件
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 + "]";
}
}
/**
* Spring中事件的抽象实现
*/
public abstract class ApplicationEvent extends EventObject {
/** 事件发生事件 */
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
/**
* 自定义实现事件
*/
public class MyApplicationEvent extends ApplicationEvent {
public MyApplicationEvent(Object source) {
super(source);
}
}
2. ApplicationListener ——Spring中的监听者接口
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* 处理发生的事件
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
/**
* 自己实现一个
*/
@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent event) {
System.out.println("MyApplicationEvent happens at : " + event.getTimestamp());
}
}
3. Spring中的多播器实现 SimpleApplicationEventMulticaster
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
/**
* 默认构造器
*/
public SimpleApplicationEventMulticaster() {
}
/**
* 带有BeanFaactory的构造器
*/
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
setBeanFactory(beanFactory);
}
/**
* 一个异步执行器
*/
public void setTaskExecutor(@Nullable Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@Nullable
protected Executor getTaskExecutor() {
return this.taskExecutor;
}
/**
* 如果有异常则使用异常处理器
*/
public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
@Nullable
protected ErrorHandler getErrorHandler() {
return this.errorHandler;
}
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
/**
* 通知指定的监听器,发生了某个指定的事件
*/
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
private boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {
// On Java 8, the message starts with the class name: "java.lang.String cannot be cast..."
if (classCastMessage.startsWith(eventClass.getName())) {
return true;
}
// On Java 11, the message starts with "class ..." a.k.a. Class.toString()
if (classCastMessage.startsWith(eventClass.toString())) {
return true;
}
// On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
int moduleSeparatorIndex = classCastMessage.indexOf('/');
if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
return true;
}
// Assuming an unrelated class cast failure...
return false;
}
}
4. 调用测试
@Component
public class EventMulticasterTestBean implements InitializingBean {
@Autowired
private ApplicationEventMulticaster applicationEventMulticaster;
@Override
public void afterPropertiesSet() throws Exception {
applicationEventMulticaster.multicastEvent(new MyApplicationEvent(new Object()));
}
}
总结
- 对比而言,第一种实现方式较为简单,比较符合正常观察者模式的思维,但是第二种实现方式更加灵活,观察者和被观察对象耦合度比较低,更适用于大型项目。
- Spring中的观察者模式贯穿了整个Spring的生命周期,具体可以看观察者模式下的SpringBoot启动过程 这篇帖子了解