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
相关推荐
Peter(阿斯拉)9 分钟前
[Java性能优化]_[时间优化]_[字符串拼接的多种方法性能分析]
java·性能优化·stringbuilder·string·字符串拼接·stringbuffer·时间优化
水痕011 小时前
gin结合minio来做文件存储
java·eureka·gin
寒士obj2 小时前
Spring事物
java·spring
柯南二号3 小时前
【Java后端】Spring Boot 集成 MyBatis-Plus 全攻略
java·spring boot·mybatis
桦说编程10 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
lifallen10 小时前
Java Stream sort算子实现:SortedOps
java·开发语言
IT毕设实战小研10 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
没有bug.的程序员11 小时前
JVM 总览与运行原理:深入Java虚拟机的核心引擎
java·jvm·python·虚拟机
甄超锋11 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国11 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端