Understanding the Singleton Design Pattern


Even beginners of object-oriented programming know that they can instantiate a class using the New keyword followed by the class's constructor, such as the following:

 New MyClass() 

or as follows:

 New MyClass(123) 

You get one object each time a constructor is called. If you call a class's constructor three times, you get three instances of the class.

Note

Even if you do not write a constructor in your class, the Visual Basic compiler creates a no-argument constructor in the absence of one. However, if a class does have a constructor, whether it is a no argument constructor or one that accepts argument(s), the Visual Basic compiler does not create a new one. These constructors are accessible because they have a public access modifier.

However, there are cases where you want to limit the number of instances of a class to one. For example, recall that in Microsoft Word you can press Ctrl+F to display a Find dialog box. However, for the whole life of Microsoft Word, there can only be one Find dialog box. If you press Ctrl+F two times, there is still only one Find dialog box. Even when there are multiple documents open, there can only be one Find dialog box that works with any active document. Indeed, you do not need more than one instance of the Find dialog box. In fact, having more than one probably will make programming harder.

For cases such as this, you use the Singleton pattern. This pattern is effective for limiting the maximum number of instances of a class to exactly one. In this case if more than one object need to use an instance of the class, those objects share the same instance. One of the reasons why you want to share an instance is to share data.

How do you do that? Because the absence of a constructor will make the compiler create a no-argument public constructor, a class applying the Singleton pattern has a private or protected constructor. Because the constructor is private or protected, there is no way you can create an instance of that class by calling its constructor. The constructor is not accessible from outside the class.

The question that arises then is this: If the only constructor cannot be accessed, how do you get an instance of that class? The answer lies in a static (shared) method in the class. A Singleton class will have a static method that calls the constructor to create an instance of the class and return this instance to the caller of the static method. But, isn't the constructor private? That's right. However, remember that the static method is also in the same class; therefore, it has access to all members of the class, including the private constructor.

You might ask the following question: "You can't create an instance of a class by calling its constructor, so how do you call the static method without having an object?" Note, though, you can use a static member of a class without having an instance of that class.

To limit the number of instances to one, the static method has to check if an instance has been created before. If it has, it simply returns a reference to the previous created instance. If it has not, it calls the constructor to create one. It is as simple as that.

As an example, consider the form whose class is called SingletonForm in Listing 2-18. This class represents a Singleton form.

Listing 2-18: A Singleton Form

start example
 Imports System Imports System.Windows.Forms Imports System.ComponentModel Public Class SingletonForm : Inherits Form   Private Shared myInstance As SingletonForm   Private Sub New()     Me.Text = "Singleton Form"   End Sub   Protected Overrides Sub OnCLosing(ByVal e As CancelEventArgs)     e.Cancel = True     Me.Hide()   End Sub   Public Shared Function GetInstance() As SingletonForm     If myInstance Is Nothing Then       myInstance = New SingletonForm()     End If     Return myInstance   End Function End Class 
end example

First, notice that the class only has one constructor and its access modifier is private. Second, to get an instance of that class, you have the static GetInstance method, and there is also a static variable called myInstance (of type SingletonForm). The GetInstance method returns the myInstance variable. The method checks if myInstance is null (Nothing) and, if yes, calls the constructor:

 If myInstance Is Nothing Then    myInstance = New SingletonForm() End If 

The method then returns myInstance.

To obtain a reference to the only instance of the SingletonForm class, you do not use its constructor. Instead, you call its GetInstance method, as in the following snippet:

 Dim myForm As SingletonForm = SingletonForm.GetInstance() 

Once you get the instance, you can call its public members just as you would a normal class's object. For example, because SingletonForm extends the Form class, you can call its Show method:

 myForm.Show() 

This application uses the Singleton pattern in the Find dialog box. Therefore, you should understand the concept well.

start sidebar
Why Not Use a Static (Shared) Object Reference?

You know that if you declare an object reference as shared, you also only have one single instance of that object. So, why bother using the Singleton pattern? Because the Singleton pattern guarantees that even if you have two or more reference variables of a Singleton class, you can only create one instance. Also, using a Singleton pattern makes it easier to change a design to allow more than one instance of a class.

end sidebar




Real World. NET Applications
Real-World .NET Applications
ISBN: 1590590821
EAN: 2147483647
Year: 2005
Pages: 82

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net