文
章
目
录
章
目
录
今天咱们就来聊聊如何用Java实现一个回调监听工具类,借助函数式接口Consumer
,可以巧妙地解耦回调方法,这样开发出来的代码结构更清晰、更易于维护。下面,我们一步步来深入了解。
一、定义监听接口类Listenable
首先,我们要创建一个抽象的监听接口Listenable
。这个接口的作用是提供一套通用的方法,用于管理和操作监听者。代码如下:
import java.util.*;
import java.util.function.Consumer;
public interface Listenable<Listener> {
// 使用WeakHashMap来存储监听者,避免内存泄漏,键为当前对象,值为对应监听者的集合
WeakHashMap<Object, Set> LISTENERS_WEAK_MAP = new WeakHashMap<>();
// 注册监听者的方法
default void registerListener(Listener listener) {
// 检查传入的监听者是否为空,若为空则抛出异常
Objects.requireNonNull(listener);
Set<Listener> listeners;
// 同步访问LISTENERS_WEAK_MAP,确保线程安全
synchronized (LISTENERS_WEAK_MAP) {
// 获取当前对象对应的监听者集合
listeners = LISTENERS_WEAK_MAP.get(this);
// 如果集合为空,则创建一个新的HashSet
if (listeners == null) {
listeners = new HashSet<>();
// 将新创建的集合存入LISTENERS_WEAK_MAP中
LISTENERS_WEAK_MAP.put(this, listeners);
}
}
// 同步访问监听者集合,确保线程安全地添加监听者
synchronized (listeners) {
listeners.add(listener);
}
}
// 注销监听者的方法
default void unregisterListener(Listener listener) {
// 检查传入的监听者是否为空,若为空则抛出异常
Objects.requireNonNull(listener);
Set<Listener> listeners;
// 同步访问LISTENERS_WEAK_MAP,确保线程安全
synchronized (LISTENERS_WEAK_MAP) {
// 获取当前对象对应的监听者集合
listeners = LISTENERS_WEAK_MAP.get(this);
// 如果集合为空,直接返回,无需进行后续操作
if (listeners == null) {
return;
}
}
// 同步访问监听者集合,确保线程安全地移除监听者
synchronized (listeners) {
listeners.remove(listener);
}
}
// 获取所有监听者的方法
default Collection<Listener> getListeners() {
// 同步访问LISTENERS_WEAK_MAP,确保线程安全
synchronized (LISTENERS_WEAK_MAP) {
// 获取当前对象对应的监听者集合
Set<Listener> listeners = LISTENERS_WEAK_MAP.get(this);
// 如果集合为空,返回一个空的HashSet
if (listeners == null) {
return new HashSet<>();
}
// 返回一个包含所有监听者的新HashSet,避免直接返回原集合导致外部修改
return new HashSet<>(listeners);
}
}
// 检查某个监听者是否已注册的方法
default boolean isListenerRegistered(Listener listener) {
// 同步访问LISTENERS_WEAK_MAP,确保线程安全
synchronized (LISTENERS_WEAK_MAP) {
// 获取当前对象对应的监听者集合
Set<Listener> listeners = LISTENERS_WEAK_MAP.get(this);
// 如果集合为空,说明监听者未注册,返回false
if (listeners == null) {
return false;
}
// 检查集合中是否包含指定的监听者
return listeners.contains(listener);
}
}
// 遍历所有监听者并执行指定操作的方法,默认忽略异常
default void forEachListener(Consumer<Listener> action) {
forEachListener(action, true);
}
// 遍历所有监听者并执行指定操作的方法,可选择是否忽略异常
default void forEachListener(Consumer<Listener> action, boolean ignoreException) {
// 检查传入的操作是否为空,若为空则抛出异常
Objects.requireNonNull(action);
Iterable<Listener> listeners;
// 同步访问LISTENERS_WEAK_MAP,确保线程安全
synchronized (LISTENERS_WEAK_MAP) {
// 获取当前对象对应的监听者集合
Set<Listener> values = LISTENERS_WEAK_MAP.get(this);
// 如果集合为空,直接返回,无需进行后续操作
if (values == null) {
return;
}
// 将监听者集合转换为ArrayList,以便进行遍历
listeners = new ArrayList<>(values);
}
// 遍历监听者列表,对每个监听者执行指定操作
for (Listener listener : listeners) {
try {
action.accept(listener);
} catch (Exception e) {
// 如果不忽略异常,则抛出捕获到的异常
if (!ignoreException) {
throw e;
}
}
}
}
}
这个接口定义了一系列方法,包括注册监听者、注销监听者、获取所有监听者、检查监听者是否注册,以及遍历所有监听者并执行指定操作等。通过这些方法,我们可以方便地管理和操作监听者。
二、实际用法示例
了解了监听接口类的定义后,我们来看一下它在实际中的用法。下面以MessageManager
类为例,展示如何使用这个监听接口来实现自定义的回调功能。
public class Main {
// 定义MessageManager类,实现Listenable接口,监听类型为OnEventListener
public static class MessageManager implements Listenable<MessageManager.OnEventListener> {
// 私有化构造函数,确保单例模式
private MessageManager() {}
// 定义单例实例
private static final MessageManager instance = new MessageManager();
// 获取单例实例的方法
public static MessageManager getInstance() {
return instance;
}
// 当操作成功时,通知所有监听者的方法
public void onSuccess(String json) {
// 遍历所有监听者,并调用它们的onSuccess方法
forEachListener(it->it.onSuccess(json));
}
// 当操作出错时,通知所有监听者的方法
public void onError(int code, String error) {
// 遍历所有监听者,并调用它们的onError方法
forEachListener(it->it.onError(code, error));
}
// 定义监听者接口,包含操作成功和操作出错的回调方法
public interface OnEventListener {
void onSuccess(String json);
void onError(int code, String error);
}
}
public static void main(String[] args) {
// 注册一个监听者
MessageManager.getInstance().registerListener(new MessageManager.OnEventListener() {
@Override
public void onSuccess(String json) {
// 操作成功时的回调处理
System.out.println("onSuccess " + json);
}
@Override
public void onError(int code, String error) {
// 操作出错时的回调处理
System.out.println("onError code:" + code + " error:" + error);
}
});
// 模拟操作成功,调用onSuccess方法通知监听者
MessageManager.getInstance().onSuccess("My json");
// 模拟操作出错,调用onError方法通知监听者
MessageManager.getInstance().onError(-1, "Error");
}
}
在这个示例中,MessageManager
类实现了Listenable
接口,并定义了自己的监听者接口OnEventListener
,包含onSuccess
和onError
两个回调方法。在main
方法中,我们注册了一个监听者,并分别调用onSuccess
和onError
方法,模拟操作成功和出错的情况,观察监听者的回调处理。运行代码后,控制台会输出以下结果:
onSuccess My json
onError code:-1 error:Error
这表明我们成功实现了回调监听功能,当MessageManager
中的操作状态发生变化时,注册的监听者能够及时收到通知并执行相应的处理逻辑。
通过上述步骤,我们成功实现了一个Java回调监听工具类,并展示了它的实际用法。这种方式可以帮助我们在开发过程中,更好地实现对象间的事件通信,提高代码的灵活性和可维护性。希望大家通过这篇文章,对Java的回调监听机制有更深入的理解和掌握。