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
相关推荐
左左右右左右摇晃8 分钟前
Java并发——synchronized锁
java·开发语言
sxlishaobin1 小时前
Java I/O 模型详解:BIO、NIO、AIO
java·开发语言·nio
彭于晏Yan1 小时前
Spring AI(二):入门使用
java·spring boot·spring·ai
有一个好名字1 小时前
vibe codeing 开发流程
java
兑生1 小时前
【灵神题单·贪心】3745. 三元素表达式的最大值 | 排序贪心 | Java
java·开发语言
polaris06301 小时前
Windows操作系统部署Tomcat详细讲解
java·windows·tomcat
卓怡学长2 小时前
m280本科生导师指导平台
java·数据库·spring·tomcat·maven·intellij-idea
一直都在5722 小时前
Java死锁
java·开发语言
我真会写代码3 小时前
深度解析并发编程锁升级:从偏向锁到重量级锁,底层原理+面试考点全拆解
java·并发编程·
Meepo_haha3 小时前
创建Spring Initializr项目
java·后端·spring