Technical articles, including those at About Visual Basic, usually discuss the detailed syntax of VB.NET, not the overall philosophy of why you might want to do things in a certain way. Design Patterns, on the other hand, are all about the why and how of programming, not the syntax. This article, one of a series about design patterns in VB.NET, discusses what might be the most popular design pattern, the Singleton pattern.
The general topic of design is one that usually turns to "design patterns". If you think syntax is hard, you have another page to turn. There are dozens of design patterns and a lot of books get written about them. In fact, you could do a lot worse than the (somewhat dated now) book Visual Basic Design Patterns.
Just to be clear, "Design Patterns" are actual code prototypes. A book like Fred Brooks' classic The Design of Design is about the overall management of the process.
"Design patterns" are not standards. Even the names vary among design gurus and variations also exist in how they're implemented. But there is quite a bit of broad agreement about the overall structure of design patterns and learning about them beats reinventing the wheel every time.
The Singleton Pattern
The main idea behind the Singleton design pattern is to make sure that your code always works with the same instance of an object. If you need more on classes and instantiation, try this introduction: Modules, Structures, and Classes.
In uncharacteristically clear language, Microsoft defines the problem solved by the Singleton design pattern like this:
How do you make an instance of an object globally available and guarantee that only one instance of the class is created?
To get the point across, here's an example of non-singleton object creation. Actually, this is just garden-variety creation of an object. The class is just a shell:
Public Class NormalClass ' This class does nothing End Class
The code that instantiates two instances confirms that they are separate instances:
Dim NormalObject1 As New NormalClass Dim NormalObject2 As New NormalClass Console.WriteLine( "NormalObject1==NormalObject2: " + (NormalObject1 Is NormalObject2).ToString())
This results in ...
... in the Output window.
What if you need to make sure that, no matter what, your code always returns the same object? For example, it might be a device interface where there is only one device. Or it might be a new account object. You wouldn't want the same account number returned as a property in two different objects!
The key technique used by the Singleton design pattern is to control the instantiation (the New subroutine in the class). Instantiation is covered in this About Visual Basic article: Coding New Instances of Objects.
Once a single instance of the class is instantiated, another reference to the class should return the same instance. The typical code that does this trick looks like this:
Public Class SingletonClass Private Shared singleInstance As SingletonClass Private Sub New() ' In this case, the Sub does nothing End Sub Public Shared ReadOnly Property Instance() _ As SingletonClass Get If singleInstance Is Nothing Then singleInstance = New SingletonClass End If Return singleInstance End Get End Property End Class
Things to notice:
-> The singleInstance variable is a shared instance of the class itself. ("Shared" is covered in this article: Shared Variables in VB.NET.)
-> New doesn't have to do anything. It just has to be here. This prevents a New subroutine from being created by the compiler.
-> The Instance property is of the type of the class itself. The first time it's referenced, one copy of the class is created and returned. After that, the same copy is returned.
Running the same code to test the pattern yields a different result:
Dim SingletonObject1 As SingletonClass = SingletonClass.Instance Dim SingletonObject2 As SingletonClass = SingletonClass.Instance Console.WriteLine( "SingletonObject1==SingletonObject2: " + (SingletonObject1 Is SingletonObject2).ToString())
The Output window now displays:
On the next page, we show a real example that you can use to balance the load among a set of servers.