Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 简单工厂模式-在设计时为扩展混凝土实例的属性指定值_Vb.net_Design Patterns_Factory Pattern - Fatal编程技术网

Vb.net 简单工厂模式-在设计时为扩展混凝土实例的属性指定值

Vb.net 简单工厂模式-在设计时为扩展混凝土实例的属性指定值,vb.net,design-patterns,factory-pattern,Vb.net,Design Patterns,Factory Pattern,我有以下子类CentreAddress和VenueAddress,它们是从基抽象类BaseAddress扩展而来的 我正在考虑实现一个简单的工厂,AddressFactory,为我的中心和场馆类创建CentreAddress和VenueAddress的具体实例 但是,我的实现不允许我在设计时为扩展的具体实例的属性赋值 在运行时,将创建正确的具体实例 我可以更改center.Address和vention.Address的返回类型,但这肯定会破坏AddressFactory作为应用程序中唯一引用具

我有以下子类CentreAddress和VenueAddress,它们是从基抽象类BaseAddress扩展而来的

我正在考虑实现一个简单的工厂,AddressFactory,为我的中心和场馆类创建CentreAddress和VenueAddress的具体实例

但是,我的实现不允许我在设计时为扩展的具体实例的属性赋值

在运行时,将创建正确的具体实例

我可以更改center.Address和vention.Address的返回类型,但这肯定会破坏AddressFactory作为应用程序中唯一引用具体类的部分的优势

我的实现正确吗?或者模式在这里不适合自己,即在不需要的时候尝试填充模式?代码如下

多谢各位

Sub Main()

    Dim centre1 = New Centre
    centre1.Name = "Centre 1"
    centre1.Address.Line1 = "Address Line 1"
    centre1.Address.Line2 = "Address Line 2"
    'centre1.Address.Line3 = "Address Line 3"  not allowed

    Dim venue1 = New Venue
    venue1.Name = "Venue 1"
    venue1.Address.Line1 = "Address Line 1"
    venue1.Address.Line2 = "Address Line 2"
    'venue1.Address.County.Name = "Bath and NE Somerset"  not allowed

End Sub

Public Class CentreAddress
    Inherits BaseAddress

    Public Property Line3 As String

End Class

Public Class VenueAddress
    Inherits BaseAddress

    Public Property County As County

End Class

Public Class County

    Public Property Name As String

End Class

Public Class Centre

    Private m_address As BaseAddress

    Public Property Name As String

    Public ReadOnly Property Address As BaseAddress
        Get
            If m_address Is Nothing Then
                m_address = AddressFactory.CreateAddress(Me)
            End If
            Return m_address
        End Get
    End Property

End Class

Public Class Venue

    Private m_address As BaseAddress

    Public Property Name As String

    Public ReadOnly Property Address As BaseAddress
        Get
            If m_address Is Nothing Then
                m_address = AddressFactory.CreateAddress(Me)
            End If
            Return m_address
        End Get
    End Property

End Class

Public Class AddressFactory

    Public Shared Function CreateAddress(objectType As Object) As BaseAddress

        If TypeOf objectType Is Venue Then
            Dim venueAddress As New VenueAddress With {.County = New County}
            Return venueAddress
        ElseIf TypeOf objectType Is Centre Then
            Return New CentreAddress
        Else
            Return New VenueAddress
        End If

    End Function

End Class

为什么不使用受保护的MustOverride函数CreateAddress()从公共基类派生Centre和Venue?您只需在相应的派生类中重写此函数。您甚至可以通过使用
new
关键字覆盖Address属性来更改其类型。在我看来,没有必要采用工厂模式。
除此之外,我看不出有什么问题。

一个工厂有两个不同的方法,每个方法都返回特定的派生类型,这没有什么问题。例如:

Public Class AddressFactory
    Public Shared Function CreateCentreAddress() As CentreAddress
        Return New CentreAddress()
    End Function

    Public Shared Function CreateVenueAddress() As VenueAddress
        Return New VenueAddress()
    End Function
End Class
Public Sub DoSomethingWithVenue()
    Dim venueAddress As VenueAddress = factory.CreateVenueAddress()
    venueAddress.County = New County()
    ' ...
    DoSomethingWithAnyAddress(venueAddress)
End Sub

Public Sub DoSomethingWithCentre()
    Dim centreAddress As CentreAddress = factory.CreateCentreAddress()
    centreAddress.Line3 = "my line 3"
    ' ...
    DoSomethingWithAnyAddress(centreAddress)
End Sub

Public Sub DoSomethingWithAnyAddress(address As BaseAddress)
    address.Name = "my name"
    ' ...
End Sub
通常,这正是你想要和需要的工厂类型。当派生的特定属性不适用时,您仍然可以编写通用代码来处理基址。例如:

Public Class AddressFactory
    Public Shared Function CreateCentreAddress() As CentreAddress
        Return New CentreAddress()
    End Function

    Public Shared Function CreateVenueAddress() As VenueAddress
        Return New VenueAddress()
    End Function
End Class
Public Sub DoSomethingWithVenue()
    Dim venueAddress As VenueAddress = factory.CreateVenueAddress()
    venueAddress.County = New County()
    ' ...
    DoSomethingWithAnyAddress(venueAddress)
End Sub

Public Sub DoSomethingWithCentre()
    Dim centreAddress As CentreAddress = factory.CreateCentreAddress()
    centreAddress.Line3 = "my line 3"
    ' ...
    DoSomethingWithAnyAddress(centreAddress)
End Sub

Public Sub DoSomethingWithAnyAddress(address As BaseAddress)
    address.Name = "my name"
    ' ...
End Sub
但是,有时确实需要工厂将对象作为基类型返回,但只有当您有需要创建对象的公共代码,但不关心创建的是哪个特定派生类型时,才会这样做。这里的情况似乎不是这样,所以我不会不必要地把自己画进一个角落。如果将来确实需要这样做,您仍然可以通过创建新的工厂类来实现,这些工厂类将重用原来的工厂类:

Public Interface IAddressFactory
    Public Function CreateAddress() As BaseAddress
End Interface

Public Class VenueAddressFactory
    Implements IAddressFactory

    Private _factory As New AddressFactory()

    Public Function CreateAddress() As BaseAddress
        Return _factory.CreateVenueAddress()
    End Function
End Class

Public Class CentreAddressFactory
    Implements IAddressFactory

    Private _factory As New AddressFactory()

    Public Function CreateAddress() As BaseAddress
        Return _factory.CreateCentreAddress()
    End Function
End Class

Public Class CommonAddressBusiness
    Public Sub New(factory As IAddressFactory)
        _factory = factory
    End Sub

    Private _factory As IAddressFactory

    Public Sub DoSomething()
        Dim someTypeOfAddress As BaseAddress = _factory.CreateAddress()
        ' ...
    End Sub
End Class

当您尝试设置centre1.Address.Line3时,您会遇到什么错误?我猜他会收到一条消息,告诉他类型BaseAddress没有名为Line3的属性。问题非常具体,关于想要使用工厂模式及其细节,说不需要它并不是真正的答案,在我看来。@RobForrest:你是对的,下次我会提供一个更好的答案。现在,我想这一切都是由史蒂文·多加特解释的。