0

0

通用事件监听器设计:基于观察者模式的无侵入式扩展方案

碧海醫心

碧海醫心

发布时间:2026-01-06 22:18:10

|

545人浏览过

|

来源于php中文网

原创

通用事件监听器设计:基于观察者模式的无侵入式扩展方案

本文介绍如何在不修改现有 aevent 和 bevent 类的前提下,通过观察者模式实现统一事件处理逻辑,提供可复用、松耦合的泛型事件监听机制。

在实际开发中,我们常遇到已有类结构固定、但需新增统一行为(如事件聚合、日志记录、状态同步)的场景。此时若无法修改原始类(如 AEvent、BEvent),直接继承或重写方法不可行,而“硬编码”重复逻辑又违背开闭原则。观察者模式(Observer Pattern)正是解决此类问题的理想选择——它通过引入中介者(Observer)解耦事件源与响应逻辑,实现零侵入、高扩展的监听机制。

核心思路是:将 AEvent 和 BEvent 视为独立的被观察者(Subject),由一个统一的 EventObserver 负责接收通知并协调处理。关键在于不改动原有类定义,仅通过委托(delegation)注入回调能力。以下是推荐实现:

Lessie AI
Lessie AI

一款定位为「People Search AI Agent」的AI搜索智能体

下载

✅ 推荐实现(最小侵入 + 类型安全)

// 1. 定义通用事件监听器接口(可选,提升可维护性)
interface EventListener {
    void onEventCreated(T event);
}

// 2. 统一观察者:支持多类型事件聚合与协同处理
class EventObserver {
    private final List> listeners = new ArrayList<>();

    // 注册任意类型事件处理器(泛型擦除下安全使用)
    public  void addListener(EventListener listener) {
        listeners.add(listener);
    }

    // 对外暴露统一触发入口(由各事件类调用)
    public void notifyEventCreated(Object event) {
        listeners.forEach(listener -> {
            // 运行时类型检查,确保安全调用
            if (listener instanceof EventListener) {
                try {
                    Method method = listener.getClass()
                        .getMethod("onEventCreated", event.getClass());
                    method.invoke(listener, event);
                } catch (Exception ignored) {}
            }
        });
    }
}

?️ 改造 AEvent / BEvent(仅添加委托方法,不修改业务逻辑)

class AEvent {
    private EventObserver observer;

    // 仅新增此方法,不破坏原有 API
    public void setObserver(EventObserver observer) {
        this.observer = observer;
    }

    public void onAEventCreate(A event) {
        // 原有业务逻辑保持不变
        System.out.println("Handling A event: " + event);

        // 通知观察者(统一入口)
        if (observer != null) {
            observer.notifyEventCreated(event);
        }
    }
}

class BEvent {
    private EventObserver observer;

    public void setObserver(EventObserver observer) {
        this.observer = observer;
    }

    public void onBEventCreate(B event) {
        System.out.println("Handling B event: " + event);
        if (observer != null) {
            observer.notifyEventCreated(event);
        }
    }
}

? 使用示例

public class UsageExample {
    public static void main(String[] args) {
        EventObserver observer = new EventObserver();

        // 注册统一处理器(支持不同事件类型)
        observer.addListener((EventListener) a -> 
            System.out.println("✅ Unified handler for A: " + a));
        observer.addListener((EventListener) b -> 
            System.out.println("✅ Unified handler for B: " + b));

        AEvent aEvent = new AEvent();
        BEvent bEvent = new BEvent();

        aEvent.setObserver(observer);
        bEvent.setObserver(observer);

        aEvent.onAEventCreate(new A()); // → 触发 A 处理器
        bEvent.onBEventCreate(new B()); // → 触发 B 处理器
    }
}

⚠️ 注意事项与进阶建议

  • 避免强耦合:EventObserver 不应持有 AEvent/BEvent 实例引用,仅通过回调通信;
  • 线程安全:若事件在多线程环境触发,notifyEventCreated() 应加锁或使用 CopyOnWriteArrayList;
  • 生命周期管理:建议增加 removeListener() 方法防止内存泄漏;
  • 替代方案对比
    • 策略模式:适用于行为差异大、需运行时切换,但需改造调用方;
    • 访问者模式:适合复杂对象结构遍历,此处过度设计;
    • 事件总线(如 EventBus):适合大型系统,但引入第三方依赖,轻量场景不必要。

综上,观察者模式以极小改造成本实现了关注点分离——原始类专注自身职责,观察者专注聚合响应。这不仅是技术方案,更是面向演进系统的设计哲学:让变化发生于可插拔的组件之间,而非固化的类内部。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

480

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

143

2025.12.24

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

38

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

52

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

10

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.1万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.1万人学习

Sass 教程
Sass 教程

共14课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号