Pat*_*ick 1 inheritance ms-access vba abstract-class factory
我有一个相对复杂的Access 2007用VBA编写的应用程序(4个枚举,7个模块,38个类模块,86个表单,以及一大堆表和查询).我发现使用对象工厂设计是有益的,但到目前为止,我无法找到一种干净的方法来实现这种类型的功能,而无需在VB或C#中轻松实现的标准抽象/继承.
有没有人有过在VBA中实施工厂设计的经验,甚至可能吗?......还是有一个巧妙的"技巧"可以帮助我获得相同的总体目标?
我在工厂设计方面的经验仅限于C#,我从来没有在VB中完成它,所以也许VBA中有一些我不知道的VB常见的东西.
例
我将收到具体日期.根据该日期,我需要计算2到5个其他日期之间的任何地方.计算这些日期的规则根据输入日期的"类型"而变化.
因此,如果我的日期为07/15/2009,这是一个类型1日期,它将返回
07/15/2010日期1,07/15/2011日期2,07/15/2012日期3,06/10/2012,日期4和07/10/2012,日期5
如果我把相同的日期,但把它作为日期类型2我将得到null为日期1,null为日期2,null为日期3,06/10/2011为日期4和07/10/2011为日期5
因此,对于每组规则,最少有3个可能的最大值为6(现在这可以随时扩展)我将基本上输入一个开始日期...规则...并返回一个对象包含所有日期属性.
我希望这有点帮助.
我可能错过了问题的重点,但为什么不在标准模块中使用"工厂"方法/"构造函数":
'default constructor
Public Function MyClassFactory() As MyClass
Set MyClassFactory = New MyClass
End Function
Run Code Online (Sandbox Code Playgroud)
或者,如果您需要带有参数的"构造函数":
'Constructor with parameters
Public Function MyClassFactory(Param1 As ParamObject1, Param2 As ParamObject2) As MyClass
Dim MyThing As MyClass
Set MyThing = New MyClass
'MyObjectInitializer is a Sub that does what a constructor should do
MyThing.MyObjectInitializer Param1, Param2
Set MyClassFactory = MyThing
End Function
Run Code Online (Sandbox Code Playgroud)
等等
如果您始终使用此方法创建MyObject实例,则此"工厂模式"将替换构造函数.
您可以修改此代码以仅创建单例等.有时,VBA的缺点(例如,具有全局范围的标准模块)可以变成有用的东西.
要打电话给你,你只需:
Dim Thing As MyClass
Set Thing = MyClassFactory(Param1, Param2)
Run Code Online (Sandbox Code Playgroud)
有了这种东西,你很接近有一个构造函数......或者一个工厂......
我肯定错过了什么.我对Factory模式的理解可能过于简单,但是你可能不希望在VBA中过于复杂.如果您发现需要,可能存在设计问题.
这是一种在 VBA 中实现工厂模式的方法,Rubberduck 网站上对此进行了很好的描述https://rubberduckvba.wordpress.com/2016/07/05/oop-vba-pt-2-factories-and-cheap-酒店/ . 这是我试图解释的。我知道可能有一种更简洁的方法来做到这一点,但我试图演示两件事:使用工厂模式和依赖注入来构造对象,而无需新建它们;以及在VBA中使用多态性的能力,使得抽象接口类可以有多种不同的实现。开放反馈。开始:
Run Code Online (Sandbox Code Playgroud)Option Explicit Public Property Get Firstname() As String End Property Public Property Get Lastname() As String End Property Public Function ToString() As String End Function
Run Code Online (Sandbox Code Playgroud)Option Explicit Private Type TExample Firstname As String Lastname As String End Type Private this As TExample Implements IExampleClass Public Property Get Firstname() As String FirstName = this.Firstname End Property Public Property Let Firstname(Value As String) this.Firstname = Value End Property Public Property Get Lastname() As String Lastname = this.Lastname End Property Public Property Let Lastname(Value As String) this.Lastname = Value End Property Public Property Get Self() As IExampleClass Set Self = Me End Property Public Function Create(ByVal First As String, ByVal Last As String) With New ExampleClass this.Firstname = First this.Lastname = Last Set Create = Self End With End Function Private Property Get IExampleClass_Firstname() As String IExampleClass_Firstname = this.Firstname End Property Private Property Get IExampleClass_Lastname() As String IExampleClass_Lastname = this.Lastname End Property Private Function IExampleClass_ToString() As String IExampleClass_ToString = this.Firstname & " " & this.Lastname End Function
请注意,在此类中,Interface 中的每个成员的实现都具有私有签名,因此使用此ExampleClass 的代码只能从IExampleClass 接口(抽象)对象访问ToString 方法。
Run Code Online (Sandbox Code Playgroud)Option Explicit Private Type TExample Firstname As String Lastname As String End Type Private this As TExample Implements IExampleClass Public Property Get Firstname() As String Firstname = this.Firstname End Property Public Property Let Firstname(Value As String) this.Firstname = Value End Property Public Property Get Lastname() As String Lastname = this.Lastname End Property Public Property Let Lastname(Value As String) this.Lastname = Value End Property Public Property Get Self() As IExampleClass Set Self = Me End Property Public Function Create(ByVal First As String, ByVal Last As String) With New ExampleClass this.Firstname = First this.Lastname = Last Set Create = Self End With End Function Private Property Get IBackwardsExampleClass_Firstname() As String IExampleClass_Firstname = this.Firstname End Property Private Property Get IBackwardsExampleClass_Lastname() As String IExampleClass_Lastname = this.Lastname End Property Private Function IBackwardsExampleClass_ToString() As String IExampleClass_ToString = this.Lastname & ", " & this.Firstname End Function
这是使这个工厂类工作的技巧,这样你就不需要使用 New 关键字来使用工厂,因此你可以使用依赖注入。这是允许您将工厂设置为单例的技巧。现在...您需要从项目中删除ExampleClass和BackwardsExampleClass,将其导出到文件夹中,在文本编辑器中打开每个.cls文件,将预声明属性设置为“True”,保存每个.cls文件,然后重新导入将两个类文件添加到您的项目中。其作用是创建这两个实现 IExampleClass 接口的“Factory”类的默认实例。
现在在立即窗格中输入:
Run Code Online (Sandbox Code Playgroud)Debug.print ExampleClass.Create("John","Smith").ToString
它将返回输出“John Smith”
下一步 在立即窗格中输入:
Run Code Online (Sandbox Code Playgroud)Debug.print BackwardsExampleClass.Create("John","Smith").ToString
它将返回输出“Smith, John”