VBA工厂类循环引用致应用崩溃,求快速/优雅修复方案
Excel VBA工厂方法循环引用崩溃的修复方案
在Excel VBA项目中,我定义了多个类与接口:工作簿的每个工作表对应一个clsPmModule类的实例,这些实例由clsFactory类中的独立工厂方法创建。
基于OOP原则,工厂方法构建的类会调用其他工厂方法,动态创建并提供其他类的实例。此外,clsPmModule的每个实例可拥有观察者(OOP观察者模式),该类实现了IObservable与IObserver接口,并提供公共方法addObserver。
目前出现工厂方法调用的循环引用问题,导致应用崩溃。我曾尝试单例模式或通过自定义构造函数传递集合替代工厂方法调用,但未解决问题,求快速或优雅的修复方案?
clsFactory代码如下:
Public Function buildSomeInstance as clsPmModule Set buildSomeInstance = new clsPmModule with buildSomeInstance .constructor(...) '自定义构造函数 .addObserver buildAnotherInstance end with end function Public Function buildAnotherInstance as clsPmModule Set buildAnotherInstance = new clsPmModule With buildAnotherInstance .constructor(...) '自定义构造函数 .bindValidationSource(buildSomeInstance) '循环引用 End With End Function
修复方案
方案1:拆分实例创建与依赖绑定(最优雅)
把实例创建和依赖关系绑定完全拆分,工厂只负责产出实例,单独用方法处理依赖关联,彻底规避循环调用:
- 修改
clsFactory,拆分职责:
' 仅负责创建实例,不处理任何依赖 Public Function createSomeInstance() as clsPmModule Set createSomeInstance = new clsPmModule createSomeInstance.constructor(...) End Function Public Function createAnotherInstance() as clsPmModule Set createAnotherInstance = new clsPmModule createAnotherInstance.constructor(...) End Function ' 单独处理依赖绑定逻辑 Public Sub initDependencies(someInst as clsPmModule, anotherInst as clsPmModule) someInst.addObserver anotherInst anotherInst.bindValidationSource someInst End Sub
- 调用时先创建所有实例,再绑定依赖:
Dim someMod as clsPmModule, anotherMod as clsPmModule Set someMod = clsFactory.createSomeInstance() Set anotherMod = clsFactory.createAnotherInstance() clsFactory.initDependencies someMod, anotherMod
方案2:延迟初始化依赖(快速修复)
如果不想大改现有结构,可将依赖改为延迟加载,不在工厂方法内直接触发对方实例的创建:
- 在
clsPmModule中新增属性存储依赖引用,把绑定逻辑移到属性赋值时:
' clsPmModule类中添加 Private m_validationSource as clsPmModule Private m_observer as clsPmModule Public Property Set ValidationSource(source as clsPmModule) Set m_validationSource = source ' 这里执行原本bindValidationSource中的初始化逻辑 End Property Public Property Set Observer(obs as clsPmModule) Set m_observer = obs Me.addObserver obs End Property
- 修改工厂方法,仅完成实例基础构造:
Public Function buildSomeInstance() as clsPmModule Set buildSomeInstance = new clsPmModule buildSomeInstance.constructor(...) End Function Public Function buildAnotherInstance() as clsPmModule Set buildAnotherInstance = new clsPmModule buildAnotherInstance.constructor(...) End Function
- 调用时手动赋值依赖:
Dim someMod as clsPmModule, anotherMod as clsPmModule Set someMod = clsFactory.buildSomeInstance() Set anotherMod = clsFactory.buildAnotherInstance() Set someMod.Observer = anotherMod Set anotherMod.ValidationSource = someMod
方案3:调整依赖绑定触发时机
通过事件或回调延迟依赖绑定,确保两个实例都已创建完成再建立引用:
比如在clsPmModule中添加实例创建完成的自定义事件,buildSomeInstance创建实例后订阅该事件,等anotherInstance创建完成后再执行addObserver;同理buildAnotherInstance也通过事件触发绑定验证源,避免在工厂方法内直接调用对方的创建方法。
内容的提问来源于stack exchange,提问作者user14181536
相关产品推荐
相关产品推荐

