refactor(core): remove ManagerRegistry singleton, use instance-based DI

Replace static getInstance() pattern with public constructor to enable
multiple independent BimEngine instances on the same page. BaseManager
and BaseDialogManager now accept registry via constructor parameter.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
yuding
2026-02-28 10:08:27 +08:00
parent fdc6f884aa
commit 963e0d6cad
3 changed files with 33 additions and 23 deletions

View File

@@ -3,6 +3,7 @@
* 提供对话框的通用生命周期管理 * 提供对话框的通用生命周期管理
*/ */
import { BaseManager } from './base-manager'; import { BaseManager } from './base-manager';
import { ManagerRegistry } from './manager-registry';
import { BimDialog } from '../components/dialog'; import { BimDialog } from '../components/dialog';
/** 对话框配置选项 */ /** 对话框配置选项 */
@@ -23,6 +24,10 @@ export abstract class BaseDialogManager extends BaseManager {
/** 对话框是否可见 */ /** 对话框是否可见 */
protected isVisible: boolean = false; protected isVisible: boolean = false;
constructor(registry: ManagerRegistry) {
super(registry);
}
/** 对话框唯一标识(子类必须实现) */ /** 对话框唯一标识(子类必须实现) */
protected abstract get dialogId(): string; protected abstract get dialogId(): string;
/** 对话框标题,支持国际化 key子类必须实现 */ /** 对话框标题,支持国际化 key子类必须实现 */

View File

@@ -7,7 +7,7 @@ import type { EngineEvents } from '../types/events';
/** /**
* Manager 抽象基类 * Manager 抽象基类
* - 自动获取 Registry 实例 * - 通过构造函数接收 Registry 实例
* - 自动管理事件订阅的清理 * - 自动管理事件订阅的清理
*/ */
export abstract class BaseManager { export abstract class BaseManager {
@@ -16,8 +16,8 @@ export abstract class BaseManager {
/** 事件订阅列表,用于自动清理 */ /** 事件订阅列表,用于自动清理 */
private subscriptions: Array<() => void> = []; private subscriptions: Array<() => void> = [];
constructor() { constructor(registry: ManagerRegistry) {
this.registry = ManagerRegistry.getInstance(); this.registry = registry;
} }
/** /**

View File

@@ -1,6 +1,6 @@
/** /**
* Manager 注册表 * Manager 注册表
* 全局单例,提供所有 Manager 的集中访问点 * 每个 BimEngine 实例持有独立的 Registry实现多实例隔离
*/ */
import { EventEmitter } from './event-emitter'; import { EventEmitter } from './event-emitter';
import type { EngineEvents } from '../types/events'; import type { EngineEvents } from '../types/events';
@@ -24,12 +24,10 @@ import type { ComponentDetailManager } from '../managers/component-detail-manage
import type { AiChatManager } from '../managers/ai-chat-manager'; import type { AiChatManager } from '../managers/ai-chat-manager';
/** /**
* Manager 注册表 - 例模式 * Manager 注册表 - 例模式
* 提供所有 Manager 的全局访问点,替代 engine 层层传递 * 每个 BimEngine 创建独立的 Registry 实例,替代旧的全局单例
*/ */
export class ManagerRegistry { export class ManagerRegistry {
/** 单例实例 */
private static instance: ManagerRegistry | null = null;
/** 事件发射器 */ /** 事件发射器 */
private eventEmitter: EventEmitter = new EventEmitter(); private eventEmitter: EventEmitter = new EventEmitter();
@@ -72,22 +70,29 @@ export class ManagerRegistry {
/** AI 聊天管理器 */ /** AI 聊天管理器 */
public aiChat: AiChatManager | null = null; public aiChat: AiChatManager | null = null;
private constructor() {} constructor() {}
/** 获取单例实例 */ /** 重置(清理事件和引用) */
public static getInstance(): ManagerRegistry { public reset(): void {
if (!ManagerRegistry.instance) { this.eventEmitter.clear();
ManagerRegistry.instance = new ManagerRegistry(); this.container = null;
} this.wrapper = null;
return ManagerRegistry.instance; this.toolbar = null;
} this.dialog = null;
this.engine3d = null;
/** 重置单例(用于测试或重新初始化) */ this.buttonGroup = null;
public static reset(): void { this.rightKey = null;
if (ManagerRegistry.instance) { this.constructTree = null;
ManagerRegistry.instance.eventEmitter.clear(); this.measure = null;
ManagerRegistry.instance = null; this.walkControl = null;
} this.sectionPlane = null;
this.sectionAxis = null;
this.sectionBox = null;
this.walkPath = null;
this.walkPlanView = null;
this.engineInfo = null;
this.componentDetail = null;
this.aiChat = null;
} }
/** /**