今天咱们就来聊聊如何用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,包含onSuccessonError两个回调方法。在main方法中,我们注册了一个监听者,并分别调用onSuccessonError方法,模拟操作成功和出错的情况,观察监听者的回调处理。运行代码后,控制台会输出以下结果:

onSuccess My json onError code:-1 error:Error 

这表明我们成功实现了回调监听功能,当MessageManager中的操作状态发生变化时,注册的监听者能够及时收到通知并执行相应的处理逻辑。

通过上述步骤,我们成功实现了一个Java回调监听工具类,并展示了它的实际用法。这种方式可以帮助我们在开发过程中,更好地实现对象间的事件通信,提高代码的灵活性和可维护性。希望大家通过这篇文章,对Java的回调监听机制有更深入的理解和掌握。