views:

217

answers:

4

Hello.

Sometimes there is a need to initialize the singleton class with some helper values. But we can't "publish" a constructor for it. What is the workaround for this?

Attention! overloading the GetInstance or setting a color is not my idea. The color should be set only once. I would like to be sure that MyPainter paints ONLY with the initialized color. Any default color should ever be used.

For more clarity I provide a sample:

''' <summary>
''' Singleton class MyPainter
''' </summary>
Public Class MyPainter
  Private Shared _pen As Pen
  Private Shared _instance As MyPainter = Nothing

  Private Sub New()
  End Sub

  ''' <summary>
  ''' This method should be called only once, like a constructor!
  ''' </summary>
  Public Shared Sub InitializeMyPainter(ByVal defaultPenColor As Color)
    _pen = New Pen(defaultPenColor)
  End Sub


  Public Shared Function GetInstance() As MyPainter
    If _instance Is Nothing Then
      _instance = New MyPainter
    End If

    Return _instance
  End Function

  Public Sub DrawLine(ByVal g As Graphics, ByVal pointA As Point, ByVal pointB As Point)
    g.DrawLine(_pen, pointA, pointB)
  End Sub

End Class

Thanks.

+2  A: 

Could you not just overload your GetInstance method?

Dim _IsInitialized as boolean = false    
Public Shared ReadOnly Property IsInitialized() As Boolean
        Get
            Return _IsInitialized
        End Get
    End Property


Public Shared Function GetInstance() As MyPainter
        If _instance Is Nothing Then
            _instance = New MyPainter
        End If

        _IsInitialized = True
        Return _instance
    End Function

    Public Overloads Shared Function GetInstance(ByVal DefaultPenColor As Color) As MyPainter
        If _instance Is Nothing Then
            _instance = New MyPainter
            InitializeMyPainter(DefaultPenColor)
        End If

        _IsInitialized = True
        Return _instance
    End Function

Before calling the GetInstance method, check to see if it has been intialized yet. If not give it a pen color.

If MyPainter.IsInitialized then
     Dim Painter as MyPainter = MyPainter.GetInstance
Else
     Dim Painter as MyPainter - MyPainter.GetInstance(System.Drawing.Color.Red)
EndIf
brad.huffman
no, no, overloading the GetInstance was not my good idea. I would like to assure that MyPainter paints ONLY with the initialized color. Any default color by default should ever be used.
serhio
The way i overloaded GetInstance would only set the pen color once (the first time it's called). You could add an additional shared member to see if the class had been intialized. I've updated the code sample. Let me know if it's still not what you're looking for.
brad.huffman
I agree. However your function have no very transparent sense to be a public one and may induce in error (a new) developer... And secondly, only I, this singleton creator will know and remember do not forget to set the color before using it. _IsInitialized = Truein parameterless GetInstance is incorrect, because I know nothing about if the color was or not initialized.
serhio
+1  A: 

You can declare Shared constructors but they must be parameterless:

Public Class MyPainter
    Private Shared _pen As Pen

    Shared Sub New()
        _pen = New Pen(Color.White)
    End Sub

    ....

End Class

You could set the color to a sensible default in the constructor and then add a helper method to change the color if desired, much like you have in your sample:

Public Shared Sub SetColor(ByVal defaultPenColor As Color)
    _pen = New Pen(defaultPenColor)
End Sub
Ray Vernagus
+1  A: 

You could use an optional parameter in GetInstance

Public Shared Function GetInstance(Optional ByVal defaultPenColor As Color = Colors.Red) As MyPainter
    If _instance Is Nothing Then
      If defaultPenColor is nothing then
          defaultPenColor = Colors.Red
      end if
      _pen = New Pen(defaultPenColor)
      _instance = New MyPainter
    End If

    Return _instance
End Function
geoff
So depending on if the GetInstance() is called with or without parameters the first time, the following calls will get different objects?This works only if you can always be sure about who calls GetInstance() first.
Mattias Nilsson
No, they will get the same object. After all it is a singleton class. The only thing that changes is the initial pen color.
geoff
Right, that's what I meant. I just can't seem to get thoughts into words today... Still that IS a problem if you can't control the first invocation.
Mattias Nilsson
True, but whatever solution to this problem you choose, you need to control the first invocation if you want initialize with some parameters. At least this way, GetInstance always returns a valid object. Its easy to add a public method to change the values later if you like.
geoff
this is very good, by I am never sure if somebody would like to use the method with parameter. So, if we figure out that instead a Color(value type) as parameter is an reference type, I am never sure if this member is Nothing (null).
serhio
@serhio - I don't follow what you mean. The instance is always initialized on the 1st call regardless of whether a parameter is supplied or not. I've updated the code to have an additional check to see whether someone specifically passes in nothing as the parameter.
geoff
+3  A: 

If you want to initialize it only once upon creation, why not to do that inside the constructor by calling some method, that will pull parameters from somewhere? If this initialization will be called several times - transform it into separate method like setOptions.

FractalizeR
Unfortunately, MyPainter don't know itself from where to take this parameters...And the default color should be explicitly defined.
serhio