Java 实现回调监听工具类

首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个抽象的监听接口

监听接口类 Listenable

java 复制代码
import java.util.*;
import java.util.function.Consumer;

public interface Listenable<Listener> {

    WeakHashMap<Object, Set> LISTENERS_WEAK_MAP = new WeakHashMap<>();

    default void registerListener(Listener listener) {
        Objects.requireNonNull(listener);
        Set<Listener> listeners;
        synchronized (LISTENERS_WEAK_MAP) {
            listeners = LISTENERS_WEAK_MAP.get(this);
            if (listeners == null) {
                listeners = new HashSet<>();
                LISTENERS_WEAK_MAP.put(this, listeners);
            }
        }
        synchronized (listeners) {
            listeners.add(listener);
        }
    }

    default void unregisterListener(Listener listener) {
        Objects.requireNonNull(listener);
        Set<Listener> listeners;
        synchronized (LISTENERS_WEAK_MAP) {
            listeners = LISTENERS_WEAK_MAP.get(this);
            if (listeners == null) {
                return;
            }
        }
        synchronized (listeners) {
            listeners.remove(listener);
        }
    }

    default Collection<Listener> getListeners() {
        synchronized (LISTENERS_WEAK_MAP) {
            Set<Listener> listeners = LISTENERS_WEAK_MAP.get(this);
            if (listeners == null) {
                return new HashSet<>();
            }
            return new HashSet<>(listeners);
        }
    }

    default boolean isListenerRegistered(Listener listener) {
        synchronized (LISTENERS_WEAK_MAP) {
            Set<Listener> listeners = LISTENERS_WEAK_MAP.get(this);
            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;
        synchronized (LISTENERS_WEAK_MAP) {
            Set<Listener> values = LISTENERS_WEAK_MAP.get(this);
            if (values == null) {
                return;
            }
            listeners = new ArrayList<>(values);
        }
        for (Listener listener : listeners) {
            try {
                action.accept(listener);
            } catch (Exception e) {
                if (!ignoreException) {
                    throw e;
                }
            }
        }
    }


}

实际用法

用法也比较简单,在自己的实现类 MessageManager 中,写上自定义的回调 OnEventListener,然后再实现通知方法,这样就可以很方便的写各种需要一对多通知的不同类型的回调了

java 复制代码
public class Main {

    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) {
            forEachListener(it->it.onSuccess(json));
        }

        public void onError(int code, String error) {
            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);
            }
        });

        MessageManager.getInstance().onSuccess("My json");
        MessageManager.getInstance().onError(-1, "Error");
    }
}

打印结果

vbnet 复制代码
onSuccess My json
onError code:-1 error:Error
相关推荐
Code blocks2 小时前
GB28181视频服务wvp部署(一)
java·spring boot·后端
我命由我123452 小时前
Spring Boot - Spring Boot 静态资源延迟响应(使用拦截器、使用过滤器、使用 ResourceResolver)
java·spring boot·后端·spring·java-ee·intellij-idea·intellij idea
Xzh04232 小时前
前后端学习的交界
java·ajax·maven·axios·测试
豆沙沙包?3 小时前
2025年--Lc201- 378. 有序矩阵中第 K 小的元素(排序)--Java版
java·线性代数·矩阵
华仔啊3 小时前
3 分钟让你彻底搞懂 Spring 观察者和发布者模式的本质区别
java·后端
没有bug.的程序员3 小时前
服务治理与 API 网关:微服务流量管理的艺术
java·分布式·微服务·架构·wpf
宠友信息3 小时前
java微服务驱动的社区平台:友猫社区的功能模块与实现逻辑
java·开发语言·微服务
Full Stack Developme3 小时前
jdk.random 包详解
java·开发语言·python
懒羊羊不懒@3 小时前
Java基础入门
java·开发语言