locked
Factory Pattern RRS feed

  • Question

  • I’ve been struggling to understand the factory pattern. In the attached example why am I not exposing properties from Axis class when I do this

     Dim axes As New Axes()

    axes.SelectAxis("xlCategory")

    axes.

    Imports System.Text
    Public Class Axes : Inherits AxisFactory
        Private _myAxisG As AxisGroup
        Private _myType As AxisType
        Private _axisType As AxisType
        
        Public Property AxisType As AxisType
            Get
                Return _myType
            End Get
            Set(value As AxisType)
                _myType = value
            End Set
        End Property
        Public Property AxisGroup As AxisGroup
            Get
                Return _myAxisG
            End Get
            Set(value As AxisGroup)
                _myAxisG = value
            End Set
        End Property
        Public Sub New()
            _myType = AxisType
            _myAxisG = AxisGroup
        End Sub
        Public Overrides Function ToString() As String
            Dim sb As New StringBuilder()
            sb.Append(Me.AxisType)
            sb.Append(",")
            sb.Append(Me.AxisGroup)
            'sb.Append(",")
            'sb.Append(Me.ScaleType)
            Return sb.ToString()
        End Function
        Overrides Function CreateAxis(ByVal choice As String) As Axis
            Dim myAxis As Axis = Nothing
            Select Case choice
                Case "xlSeries"
                    myAxis = New SeriesAxis()
                Case "xlCategory", "xlValue"
                    myAxis = New CategoryValueAxis()
            End Select
            Return myAxis
        End Function
    End Class
    Public MustInherit Class AxisFactory
        Public Function SelectAxis(ByVal choice As String) As Axis
            Dim myAxis As Axis = Me.CreateAxis(choice)
            Return myAxis
        End Function
        MustOverride Function CreateAxis(ByVal choice As String) As Axis
    End Class


    Public Enum xlScaleType
        xlLinear = -4132
        xlLogarithmic = -4133
    End Enum
    Public Enum AxisGroup
        xlPrimary = 0
        xlSecondary = 1
    End Enum
    Public Enum AxisType
        xlCategory = 0
        xlValue = 1
        xlSeriesAxis = 2
    End Enum
    Public Class Axis
        Private _Title As String
            _
        Public Property Title() As String
            Get
                Return _Title
            End Get
            Set(value As String)
                _Title = value
            End Set
        End Property
        Public Sub New()
        End Sub
    End Class
    Class CategoryValueAxis
        Inherits Axis
        Private _ScaleType As xlScaleType = xlScaleType.xlLinear
        Public Property ScaleType As xlScaleType
            Get
                Return _ScaleType
            End Get
            Set(value As xlScaleType)
                _ScaleType = value
            End Set
        End Property
    End Class
    Class SeriesAxis
        Inherits Axis
        Private _LineStyle As String
        Sub New()
        End Sub
        Public Property LineStyle As Double
            Get
                Return _LineStyle
            End Get
            Set(value As Double)
                _LineStyle = value
            End Set
        End Property
    End Class


    Imports System.Text
    Module Module1
        Sub Main()
            Dim axes As New Axes()
            axes.SelectAxis("xlCategory")
            axes.
        End Sub
    End Module

    Your input is much appreciated,


    wesley

    Monday, June 2, 2014 8:48 PM

Answers

  • Hi Reed,

    I know I'm doing something wrong because if I did not, then by passing "xlCategory" to AxisFactory would show ScaleType Property in the intelisense.


     


    wesley


    Passing "xlCategory" to the SelectAxis method does nothing to the local instance of axes" because SelectAxis is a function which returns a new instance of Axis.

    The type Axis does not have a ScaleType property; that is a member of CategoryValueAxis.  So you need to cast the result of SelectAxis into the appropriate derived Axis class (as shown in my previous post).

    Dim axes As New Axes()
    Dim catAxis As CategoryValueAxis
    catAxis = CType(axes.SelectAxis("xlCategory"), CategoryValueAxis)


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by wes.r Wednesday, June 4, 2014 12:40 PM
    Tuesday, June 3, 2014 4:54 PM

All replies

  • Wes,

    Are you open to a different idea of how to do this (what "it" is, I'm unclear on that part right now) and if so, would you explain your goal?


    Please call me Frank :)

    Monday, June 2, 2014 8:58 PM
  • http://msdn.microsoft.com/en-us/library/dd293589.aspx

    I'll just say this. You can get rid of the private backing variables for public properties by using Auto Properties.

    Monday, June 2, 2014 9:06 PM
  • Well, for starters, this looks problematic:

        Public Sub New()
            _myType = AxisType
            _myAxisG = AxisGroup
        End Sub

    You're setting the backing field to the property value which returns the backing field... that should cause a stack overflow and may be what is preventing intellisense from revealing the type members.  This is one issue I noticed outright... there may be others hiding in there.

    But moreover, this isn't really a factory pattern.  The constructor would be protected and you would have shared methods which are used to create new instances of the class.  These shared methods could be defined on the class itself, or within a "Factory" class.  The separate factory class is typically appropriate when there is other related data affected by the creation of a new item (for instance, a container which automatically tracks instances) or when there are a lot of different kinds of constructors (as you can spread out the definitions over multiple methods and overloads).


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, June 3, 2014 12:40 AM
  • Well, for starters, this looks problematic:

        Public Sub New()
            _myType = AxisType
            _myAxisG = AxisGroup
        End Sub

    You're setting the backing field to the property value which returns the backing field... that should cause a stack overflow and may be what is preventing intellisense from revealing the type members.  This is one issue I noticed outright... there may be others hiding in there.

    But moreover, this isn't really a factory pattern.  The constructor would be protected and you would have shared methods which are used to create new instances of the class.  These shared methods could be defined on the class itself, or within a "Factory" class.  The separate factory class is typically appropriate when there is other related data affected by the creation of a new item (for instance, a container which automatically tracks instances) or when there are a lot of different kinds of constructors (as you can spread out the definitions over multiple methods and overloads).


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    There's a bit of confusion on inheritence also - but right you are ... this isn't a factory pattern.

    I was hoping to step through a different approach.

    We shall see. :)


    Please call me Frank :)

    Tuesday, June 3, 2014 12:43 AM
  • Hi Frank,

    If you inspect Excel chart object, it contains Axes collection that have to input parameters, AxisType and Axis Group. If you take a closer look at AxisType, you can pass in xlValue, xlCategory, and xlSeries.  So depending on the parameter that is being set, I need to be able to construct Axis Type with appropriate properties.

    Regards,


    wesley

    Tuesday, June 3, 2014 12:14 PM
  • Hi Reed,

    That is not it, Inherited Axis Type is still hidden.

    Thanks,


    wesley

    Tuesday, June 3, 2014 12:17 PM
  • Hi Frank,

    If you inspect Excel chart object, it contains Axes collection that have to input parameters, AxisType and Axis Group. If you take a closer look at AxisType, you can pass in xlValue, xlCategory, and xlSeries.  So depending on the parameter that is being set, I need to be able to construct Axis Type with appropriate properties.

    Regards,


    wesley

    If this it to be integrated with Excel, Kevin or someone else would be the best choice to help you with that - surely not me.

    *****

    As for what you have though, lose the ineheritence for now. It's not set up right for that and currently isn't doing anything.

    For a factory pattern (i.e., you hand it instructions, it hands you back the "product"), you need to look more closely at shared members. Everything does NOT have to be shared - depending on how you set it all up.

    As an example, very often I'll have a method (a sub) which will add a new instance to a List(Of Class) that they pass in. It does that by way of a private constructor and in fact if they attempt to use the Public Sub New, it will throw an exception back to them stating they cannot instantiate the class calling that method.

    When I then call the private constructor, it works the same as though I were using instance methods - nothing is shared in that, only the method itself is.


    Please call me Frank :)


    • Edited by Frank L. Smith Tuesday, June 3, 2014 12:51 PM ...words got jumbled somehow
    Tuesday, June 3, 2014 12:48 PM
  • Hi Reed,

    That is not it, Inherited Axis Type is still hidden.

    Thanks,


    wesley

    I don't follow... the AxisType property should be available:

    However, SelectAxis is a method which returns a new Axis instance so I would expect the code to be something more like:

    Dim axes As New Axes()
    Dim catAxis As CategoryValueAxis
    catAxis = CType(axes.SelectAxis("xlCategory"), CategoryValueAxis)
    

    While that constructor is still odd, I realize now it doesn't cause any error (it just doesn't actually do anything - its like saying _myType = _myType).


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Tuesday, June 3, 2014 2:39 PM
  • Hi Reed,

    I know I'm doing something wrong because if I did not, then by passing "xlCategory" to AxisFactory would show ScaleType Property in the intelisense.


     


    wesley


    • Edited by wes.r Tuesday, June 3, 2014 3:14 PM
    Tuesday, June 3, 2014 3:13 PM
  • Hi Reed,

    I know I'm doing something wrong because if I did not, then by passing "xlCategory" to AxisFactory would show ScaleType Property in the intelisense.


     


    wesley


    Passing "xlCategory" to the SelectAxis method does nothing to the local instance of axes" because SelectAxis is a function which returns a new instance of Axis.

    The type Axis does not have a ScaleType property; that is a member of CategoryValueAxis.  So you need to cast the result of SelectAxis into the appropriate derived Axis class (as shown in my previous post).

    Dim axes As New Axes()
    Dim catAxis As CategoryValueAxis
    catAxis = CType(axes.SelectAxis("xlCategory"), CategoryValueAxis)


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by wes.r Wednesday, June 4, 2014 12:40 PM
    Tuesday, June 3, 2014 4:54 PM
  • Hi Reed,

    Ye, the catAxis shows properties but it's not inherited by Axes class.

    Regards,


    wesley


    • Edited by wes.r Wednesday, June 4, 2014 2:43 PM
    Wednesday, June 4, 2014 12:40 PM