我有两个需要互相交互的对象,一个称为Collateral
,另一个称为Model
。 Model
是一个抽象类,由Model_A
,Model_B
,Model_AB
实现。每个Collateral对象都有一个models
集合作为其属性之一。为了初始化每个Model
,我需要使用来自Collateral
的信息(还有另一个对象可以将其称为User_Input
),该信息会因Model
的实施而异。
我的问题是可以使用一个能够知道创建它的对象的构造函数(在这种情况下Model
构造函数知道Collateral
实例化了什么)?
如果没有,我认为有人会建议我使用抽象工厂模式,如果是这样,它会是什么样子(我担心在OOP时我仍然是绿色的)?
为简单起见,假设如下:
Collateral
具有属性A,B,C,Models_Collection Collateral
为其创建的每个Run
调用过程Models
(在Models_Collection中有)Model
有一个名为Run
的公共子,它在所有类中实现Run
处理Collateral
Model_A
要求属性A初始化Model_B
要求属性B初始化Model_AB
要求属性A,B初始化以下是我认为应如下所示的简化代码:
络
Dim A, B, C as Variant
Dim Model_Collection as Collection
Sub New_Model( Model_Type as String)
Model_Collection.Add(Model_Implementation)
End Sub
Sub Execute_Models()
For Each Model in Model_Collection
Model.Run(Me)
Next Model
End Sub
模型
Sub Run()
End
Model_A
Implements Model
Sub Class_Initialize()
'Some code that takes property A from Collateral that Created this object
Sub Run(Collateral as Collateral)
'Some Code
End Sub
Model_B
Implements Model
Sub Class_Initialize()
'Some code that takes property B from Collateral that Created this object
Sub Run(Collateral as Collateral)
'Some Code
End Sub
Model_AB
Implements Model
Sub Class_Initialize()
'Some code that takes property A, and B from Collateral that Created this object
Sub Run(Collateral as Collateral)
'Some Code
End Sub
答案 0 :(得分:3)
首先,让我们回答你的问题。如何动态创建所有实现相同接口的不同类的实例?正如所指出的,VBA没有任何构造函数,因此您需要更正。这里调用工厂模式。
我倾向于如何解决这个问题,在Interface类中定义一个公共枚举,用于跟踪已实现的类。无论何时实施新的,您都需要将其添加到枚举和工厂中。它比我更喜欢维护,但如果没有适当的反思,我们就无法做到这一点。
所以,IModel
界面:
Public Enum EModel
ModelA
ModelB
ModelC
End Enum
Public Sub Run
End Sub
你的模特本身保持不变。然后返回Collateral
这样的New_Model
。
private models as Collection
Public Sub New_Model(ByVal type As EModel) As IModel
dim model As IModel
Select Case type
Case EModel.ModelA: Set model = New ModelA
Case EModel.ModelB: Set model = New ModelB
Case EModel.ModelC: Set model = New ModelC
End Select
models.Add model
End Sub
请注意,使用枚举比在示例中使用字符串更好,因此它会检查编译时错误而不是运行时。 (这消除了拼写错误的可能性。)
如果是我实现这个,我会创建一个实际的单独的类ModelFactory
。然后Collateral
会调用模型工厂来获得它所需要的东西。我认为这是一个很好的分离。
根据您的要求,实现看起来像这样。
Public Function CreateModel(Optional A As Variant, Optional B As Variant, Optional C As Variant)
If Not A Is Nothing Then
If B Is Nothing Then
Set CreateModel = New ModelA
Exit Function
Else
Set CreateModel = New ModelC
Exit Function
End If
End If
If Not B Is Nothing Then
Set CreateModel = New ModelB
Exit Function
End If
End Function
请注意,这完全取消了枚举和指定类型的需要。工厂根据可用的参数知道要创建的内容。
然后你的Collateral
课只是打电话给工厂并给它任何东西。
Private A,B,C
Private models As Collection
Private factory As ModelFactory
Private Sub Class_Initialize()
Set factory = New ModelFactory
End Sub
Public Sub New_Model()
models.Add factory.CreateModel(A,B,C)
End Sub
现在,我会先发制人地回答你的下一个问题,因为我觉得你已经开始提出问题了。
我怎样才能准确说出我的模型类型?
嗯,为此你有几个选项在this code review Q & A中有点详细说明。这取决于你的用例,但在这里它们是。
TypeName(arg)
- 返回对象的字符串名称。例如:
Dim model As IModel
Set model = New ModelA
Debug.Print TypeName(model) '=> "ModelA"
TypeOf
和Is
- 更强烈地检查变量的类型。细节在我链接的问题中,但这是一个例子。
Dim model as IModel
Set model = SomeFunctionThatReturnsAnIModel()
If TypeOf model Is ModelA Then
' take some specific action for ModelA types
Else If TypeOf model Is ModelB Then
' ModelB type specific action
Else If ...