VB.NET OOP Part 3: The Singleton Pattern

Beginners and seasoned object-oriented programmers know that they create an
instance of a class by invoking the class' constructor preceded by the New
keyword. For example, the following code constructs an instance of class
MyClass by calling its no-argument constructor:

New MyClass()

You get one object each time a constructor is called. If you call a class'
constructor three times, you get three instances of the class. Also note that
even if you don't write a constructor in your class, the VB 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
arguments, the VB compiler does not create a new one. Normally, these
constructors have a public access modifier because they are meant to be invoked
from outside of the class.

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. However, for the whole life of Microsoft Word, there
can only be one Find dialog. If you press Ctrl-F two times, there is still only
one Find dialog. Even when there are multiple documents open, there can only be
one Find dialog that works with any active document. Indeed, you don't need
more than one instance of the Find dialog. Having more than one will probably
complicate matters. (Imagine having multiple instances of the Find dialog while
editing a document in Microsoft Word.)

The Singleton pattern can be used for this purpose. 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 needs to use an instance of the Singleton class,
those objects share the same Singleton class instance. A class that implements
the Singleton pattern is called a Singleton class.

How do you write a Singleton class? Simply put: by creating a public shared
method which is solely responsible for creating the single instance of the
class. This also means that the client of the class should not be able to
invoke the Singleton class' constructor, either. 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 the client can
create an instance of that class by calling its constructor. The constructor is
not accessible from outside of the class!

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

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 shared method (responsible
for creating the single instance of the class) without having the class
instance?" Note, though, that shared members of a class can be invoked without
having an instance of that class. To limit the number of instances to one, the
shared 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's as simple as that.

Creating the SingletonForm Class

As an example, consider a form, the class of which is called SingletonForm, in Listing
1. This class represents a Singleton form.

First of all, notice that the class only has one constructor and its access
modifier is private. Secondly, to get an instance of that class, you have the
shared GetInstance method, and there is also a shared 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
don't 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' object. For example, since SingletonForm extends the Form class,
you can call its Show method.

myForm.Show()

Note that we override the OnClosing method of the Form class so that it does
not destroy the instance when the form is closed. Instead, it just hides it.

Using the SingletonForm Class

Now that you have a Singleton class, you can use it from your application. The
code in Listing 2 is a form class that has a button. When the button is
clicked, the application displays the SingletonForm class instance.

This results in the MyForm.exe file. Calling this executable will display a
form with a button, as shown in Figure 1.

Figure 1: The MyForm form that uses SingletonForm

Clicking the button displays the SingletonForm. Clicking the button several
times does not create multiple instances of Singleton. If you close the
SingletonForm, it's not disposed of, but only made hidden. The next time you click
the button in MyForm again, the same instance will be displayed. You can prove
this by checking the creation time on the title bar of the SingletonForm.