可以使用 static 字段在基类中维护全局计数器,通过封装 register/unregister 方法、构造函数自动注册、析构或 dispose 时注销、线程安全原子操作及只读接口,统一统计所有子类活跃对象总数。

可以用 static 字段在基类中维护一个全局计数器,配合构造函数和析构函数(或终结器)来统计所有子类当前的活跃对象总数。
定义 static 计数器并封装增减逻辑
在基类中声明一个 private static int 字段,并提供受控的增减方法(如 Register() 和 Unregister()),避免子类直接操作计数器,保证线程安全和逻辑一致性。
- 构造函数中调用
Register(),对象创建时加一 - 析构函数(C#)或
Dispose()(推荐)中调用Unregister(),对象释放时减一 - 若语言不支持确定性析构(如 Java),可用弱引用+引用队列或显式
close()配合 try-with-resources
确保所有子类都参与计数
基类构造函数应自动完成注册,子类无需额外代码;但必须保证所有实例都通过基类构造路径创建(即子类构造函数必须调用 base() 或等效机制)。
- 禁止子类提供无基类构造调用的构造函数(编译期可设为
protected基类构造,强制继承链) - 若存在静态工厂方法创建对象,也要在工厂内部调用
Register() - 避免反序列化绕过构造函数——可通过重写
OnDeserialized或自定义反序列化逻辑补注册
考虑线程安全与并发场景
多线程环境下,多个对象可能同时构造或销毁,++ 和 -- 非原子操作会导致计数错误。
- 使用
Interlocked.Increment/Decrement(C#)或AtomicInteger(Java)替代普通增减 - 避免在锁内做耗时操作,注册/注销本身应轻量
- 读取总数时(如
GetActiveCount())直接返回原子变量值,无需锁
提供只读访问接口
对外暴露一个静态属性或方法获取当前活跃数,不开放修改权限。
- C# 示例:
public static int ActiveCount => _count; - Java 示例:
public static int getActiveCount() { return counter.get(); } - 避免返回字段引用或可变对象,防止外部篡改
不复杂但容易忽略细节:构造与销毁必须严格配对,且覆盖所有对象生命周期入口。只要基类把控住注册点,无论多少层继承、多少个子类,计数自然统一。











