java中用接口实现观察者模式的核心是定义subject与observer契约以解耦二者,通过泛型eventhandler和eventsource接口实现类型安全与线程安全的通知机制,并辅以事件总线示例及内存泄漏、异常隔离等进阶实践。

Java 中用接口实现观察者模式,核心是定义 事件发布者(Subject) 和 事件监听者(Observer) 的契约,再通过接口解耦二者,让通知逻辑可插拔、易扩展。
定义 Observer 接口:统一监听行为
观察者需实现统一的响应方法,通常用函数式接口更简洁:
public interface EventHandler {
void onEvent(Object event);
}
也可带泛型增强类型安全:
public interface EventHandler<t> {
void handle(T event);
}</t>
这样不同事件类型(如 UserCreatedEvent、OrderPaidEvent)可对应专属监听器,编译期检查类型,避免强转错误。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
定义 Subject 接口:管理监听器与触发通知
发布者不关心具体是谁监听,只依赖接口操作:
public interface EventSource {
<t> void addListener(EventHandler<t> handler);
<t> void removeListener(EventHandler<t> handler);
<t> void fireEvent(T event);
}</t></t></t></t></t>
实际实现时常用 CopyOnWriteArrayList 存储监听器——线程安全,且遍历时支持并发修改,避免 ConcurrentModificationException。
组合实现:一个简单但可用的事件总线
用内部类或独立类实现 EventSource,例如:
public class SimpleEventBus implements EventSource {
private final Map<class>, List<eventhandler>>> listeners
= new ConcurrentHashMap();
@Override
public <t> void addListener(EventHandler<t> handler) {
Class<t> eventType = resolveEventType(handler);
listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList())
.add(handler);
}
@Override
public <t> void fireEvent(T event) {
Class<t> eventType = (Class<t>) event.getClass();
List<eventhandler>> handlers = listeners.get(eventType);
if (handlers != null) {
handlers.forEach(h -> ((EventHandler<t>) h).handle(event));
}
}
// 辅助方法:通过反射获取泛型实际类型(简化版,生产建议用 TypeResolver 等工具)
@SuppressWarnings("unchecked")
private <t> Class<t> resolveEventType(EventHandler<t> h) {
return (Class<t>) Object.class; // 实际中可结合 LambdaMetafactory 或注解推导
}
}</t></t></t></t></t></eventhandler></t></t></t></t></t></t></eventhandler></class>
使用示例:
EventSource bus = new SimpleEventBus();
bus.addListener((UserCreatedEvent e) -> System.out.println("发送欢迎邮件: " + e.getUser()));
bus.addListener((UserCreatedEvent e) -> System.out.println("初始化用户档案"));
bus.fireEvent(new UserCreatedEvent(new User("Alice")));
进阶建议:避免常见陷阱
-
内存泄漏:监听器持有外部对象引用时,记得在适当时候调用
removeListener;可考虑用WeakReference包装监听器 -
异常隔离:单个监听器抛异常不应中断其他监听器执行,
fireEvent内应 try-catch 每个 handler 调用 -
线程模型明确:默认同步通知;如需异步,可在
fireEvent中提交到线程池,并约定监听器不阻塞 -
事件不可变:传入
fireEvent的 event 对象建议设为final字段 + 无 setter,防止监听器意外篡改影响后续处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










