开发者

Is it possible to restrict instantiation of an object to only one other (parent) object in VB.NET?

VB 2008 .NET 3.5

Suppose we have two classes, Order and OrderItem, that represent some type of online ordering system. OrderItem represents a single line item in an Order. One Order can contain multiple OrderItems, in the form of a List(of OrderItem).

Public Class Order
    Public Property MyOrderItems() as List(of OrderItem)
    End Property
End Class

It makes sense that an OrderItem should not exist without an Order. In other words, an OrderItem class should not be able to be instantiated on its own, it should be dependent on an Order class to contain it and instantiate it. However, the OrderItem should be public in scope so that it's properties are accessible to other objects. So, the requirements for OrderItem are:

  1. Can only be instantiated by the Order class.

  2. Must be public so that any other object can access it's properties/metho开发者_如何学编程ds through the Order object. e.g. Order.OrderItem(0).ProductID.

  3. OrderItem should be able to be passed to other subs/functions that will operate on it.

How can I achieve these goals? Is there a better approach?


You can make a single constructor of OrderItem that takes an Order item.

In this constructor, you can add the OrderItem to the Order.MyOrderItems collection.

This will satisfy your requirements.

Public Class OrderItem
    Public Sub New(ByRef myOrder As Order)
        myOrder.MyOrderItems.Add(Me)
    End Sub
End Class
  1. You can only instantiate OrderItem by passing in a valid Order object to it.
  2. Still public and can be called as required (Order.OrderItem(0).ProductID).
  3. OrderItem can be passed to other subs and functions.


The standard way to do this is to expose the OrderItem as an interface and then implement it in a private class inside the Order class. The OrderItem class can only be instantiated inside the Order class but it can be exposed to the outside through the public IOrderItem interface. Like so:

Public Interface IOrderItem
    ReadOnly Property ItemCode() As Integer
    ReadOnly Property NumberOfItems() As Integer
    ReadOnly Property Description() As String
End Interface

Public Class Order

    Private m_Items As List(Of IOrderItem)

    Public ReadOnly Property Items() As List(Of IOrderItem)
        Get
            Return m_Items
        End Get
    End Property

    Private Class OrderItem
        Implements IOrderItem

        Private m_Code As Integer
        Private m_NumItems As Integer
        Private m_Description As String

        Public Sub New(ByVal code As Integer, ByVal numItems As Integer, ByVal desc As String)
            m_Code = code
            m_NumItems = numItems
            m_Description = desc
        End Sub

        Public ReadOnly Property Description() As String Implements IOrderItem.Description
            Get
                Return m_Description
            End Get
        End Property

        Public ReadOnly Property ItemCode() As Integer Implements IOrderItem.ItemCode
            Get
                Return m_Code
            End Get
        End Property

        Public ReadOnly Property NumberOfItems() As Integer Implements IOrderItem.NumberOfItems
            Get
                Return m_NumItems
            End Get
        End Property
    End Class
End Class


OrderItem's constructor should be friend (accesible only to Order) - I say friend because using friend you can limit the visibility of the OrderItem's constructor to classes in the same assembly. Note: this solution implies that Order and OrderItem are in one library/assembly and you are trying to use them from another assembly - otherwise the friend protection does not work.

The responsablity for creating OrderItem objects should belong only to Order:

Build a method like on the Order class: Public Function CreateOrderItem(whateverParametersYouNeed) as OrderItem that internally instantiates a new OrderItem, adds it to the OrderItem list and returns reference to the newly created item.

You can then do whatever you want with this OrderItem - it will always belong to the Order's list.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜