Before you can be expected to get excited about patterns it will be helpful to tell you what they are and why you want to know about them.
Patterns are named solutions or strategies to problems that have already been solved. Patterns have names and descriptions that describe how to implement a particular pattern, and usually there is information that describes the benefits and consequences of using a specific pattern. Most importantly is that patterns are solutions to often sticky problems that someone with a substantial amount of experience has already solved in a clever way. If you know about the pattern then you can simply borrow. Knowing about patterns is what it would be like if Michael Jordan were able to tell you how to leap and all you had to do were follow his instructions. Unfortunately physical emulation takes a substantial amount of work and natural ability. Mental emulation requires a lot of effort, too, but perhaps less natural ability.
A pattern is a general solution to a category of problem. Instead of reinventing a solution all you have to do is learn the pattern and know when to apply it. Some patterns are easier to understand and use than others.
The pattern we are going to look at is the Singleton pattern. I actually learned to use it years ago before it was called a pattern. Ten years ago or so, using Singleton objects was just referred to as Singletons. (I originally read about this pattern in a book by James Coplien, “Advanced C++”, or maybe it was one of Grady Booch’s books. It is long enough ago that I forgot the source, but the pattern is useful enough that I use it all the time.)
What is the Singleton pattern?
The Singleton pattern is quite simply a strategy for ensuring that there is only ever one instance of a particular object.
The reasons you might only want one instance of an object vary, but usually are related to there being only one physical instance of the thing the object represents. For example, you might implement a Printer class and only want one instance of the Printer class at a time. This would prevent multiple processes from trying to control the printer at a time. You might want to allow multiple processes to submit print jobs to a queue to be printed in turn, but you would not want two processes changing basic printer configurations in the middle of a print job.
Singletons occur in many circumstances. Another example might be the Application class in .NET. When an application is running, the Application object represents the running application instance. Microsoft would not want a programmer to create an instance of the Application class when the application is already running.
When you are writing classes and you have a class that represents something that can only occur one time then use the Singleton pattern to ensure that only one instance ever exists. Ensure is the operative word.
Implementing the Singleton pattern in VB.NET
The Singleton pattern is implemented in two steps. The first step is to ensure that every constructor in the class implementing the Singleton pattern is non-public. All constructors must be protected or private. The second step is to implement a public factory method-a shared method-that creates just one instance of the class.
How do a private constructor and a shared factory method ensure that there is only one instance of the class? The answer is that consumers cannot invoke non-public constructors; hence they cannot create instances of your class except in the manner you prescribe. However, member methods can invoke protected or private methods and can call your non-public constructors. The result is that you control the number of instances of your class by controlling access to the constructor.
Listing 1 demonstrates the pieces you will need to implement the Singleton pattern.
Public Class Singleton Private Shared FInstance As Singleton = Nothing Private Sub New() End Sub Public Shared ReadOnly Property Instance() Get If (FInstance Is Nothing) Then FInstance = New Singleton() End If Return FInstance End Get End Property End Class
No matter how hard a consumer tries he will not be able to create more than one instance of the Singleton class. The private shared field FInstance is used to store the reference to the instance of the Singleton. The constructor-Sub New-is private; thus Singleton objects cannot be created directly. Finally, the shared property Instance can be invoked and this will return an instance of the Singleton class but only create one instance of the class.
Implementing advanced idioms like the Singleton pattern was difficult, if not impossible, to do in Visual Basic 6. Fortunately VB.NET has been promoted to a first class language, and there is very little that we will be unable to do with the new VB.
Good programming is all about expressing your intent and controlling access to everything. When you mean constant indicate constant. When only one occurrence of an object can exist then use the Singleton pattern.
There are many patterns that offer solutions to problems that other developers have already solved. You can learn patterns one at a time or get a good book on the subject, like Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, et al.
Genius is hard work and a little inspiration standing on the shoulders of greatness. Many of the patterns that exist evolved while talented developers were solving difficult problems. This information is available for the wee cost of a book and a few hours of study.
About the Author
Paul Kimmel is a freelance writer for Developer.com and CodeGuru.com. Look for cool Visual Basic .Net topics in his book Visual Basic .Net Unleashed.
Paul founded Software Conceptions, Inc. in 1990. Contact Paul Kimmel at [email protected] for help building VB.NET applications or migrating VB6 applications to .NET.