Reputation: 28586
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.
Upvotes: 3
Views: 2185
Reputation: 23
You could use an Init-method: (It's an C# example, I just ran into the same issue with initializable singletons)
public sealed class XSingleton
{
private static XSingleton instance = null;
int value = -1;
private XSingleton(int v)
{
value = v;
}
public static void Init(int v)
{
if (instance != null) throw new Exception("Init() must be called only once!");
instance = new XSingleton(v);
}
public static XSingleton Instance
{
get
{
if (instance == null) throw new Exception("Call Init() before!");
return instance;
}
}
public int Value { get { return value; } }
}
If you try to use XSingleton unitinialized or try to initialize more than once, you get an exception.
So you initialize the singleton with
XSingleton.Init(123);
Now you can use the initialized Value:
Console.WriteLine(XSingleton.Instance.Value);
Upvotes: 0
Reputation: 137398
Create a CreateInstance
method that takes the required parameters. And remove the creation ability from GetInstance
. Not totally a singleton then, but at least you KNOW things are going to be initialized correctly.
Upvotes: 0
Reputation: 1271
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
Upvotes: 2
Reputation: 18832
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
Upvotes: 1
Reputation: 29985
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.
Upvotes: 3
Reputation: 6150
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
Upvotes: 1