The Singleton Pattern is one of the more useful design patterns I've run across. Not because it can be used everywhere, it actually has very few applications where it's needed, BUT when it can be applied it makes things so much easier. Sometimes you just need one instance of a class for the lifetime of the application, but you might need that instance in a large variety of locations in your code, such as if you had a class with a connection to a file, another computer or a database but in several different places in your project you need that connection. Without this pattern, you either elevate the scope of that instance to a global status or you pass the instance to every method that needs it, leading to complications about having it available in methods that don't need it, e.g. if your main method calls methodA, methodA calls methodB, and methodB needs this instance, you'll have to pass it through methodA that doesn't need it. So what's the answer? How can an instance be accessible anywhere without losing control of the scope? The Singleton Pattern is how!!! Simple to implement, a Singleton Pattern entails changing only a few things to a normal class. All you have to do is make the constructor private and provide a public static method, traditionally named GetInstance(), and it either makes the first instance, or it returns that instance.
public class SingletonExample {
private static SingletonExample _singleton = null;
private SingletonExample() { }
public static SingletonExample GetInstance() {
if (_singleton == null) {
_singleton = new SingletonExample();
}
return _singleton;
}
}
Bam, you now have a Singleton class! Just call SingletonExample.GetInstance() instead of creating a new instance (which you can't even do since the constructor is private), you get the exact same instance. From here on out, you are free to design the class like any other class with private and public methods and properties. To me, it's one of the simplest design patterns to implement and it solves a big design problem.
What if I need a limited number of instance for a limited number of connections and want to use this great pattern to keep those instances available anywhere in my code? That's an oddly specific question, with an equally oddly specific answer! The Multiton Pattern! It's just a subtle change from the Singleton while having the same results.
public class MultitonExample {
private static Hashtable _multiton = new Hashtable();
private MultitonExample() { }
public static MultitonExample GetInstance(String instanceName) {
if (!_multiton.ContainsKey(instanceName)) {
_multiton.Add(instanceName, new MultitonExample());
}
return (MultitonExample)_multiton[instanceName];
}
}
If you follow it, if you call GetInstance with one string, you would receive a different instance than if you passed a different string. This isn't limited to strings either, a better alternative might be to use a struct with constructor parameters, if that struct hasn't already been used to create an instance and store that instance, then the struct can be used to create a new instance with different parameters. Maybe we wanted to use a Multiton to connect to multiple computers on a network, we could make a few changes like the following:
public class MultitonExample {
private static Hashtable _multiton = new Hashtable();
public String IPAddress {
get;
private set;
}
public int Port {
get;
private set;
}
private MultitonExample(ConnectionInfo info) {
this.IPAddress = info.IPAddress;
this.Port = info.Port;
}
public static MultitonExample GetInstance(ConnectionInfo instanceInfo) {
if (!_multiton.ContainsKey(instanceInfo)) {
_multiton.Add(instanceInfo, new MultitonExample(instanceInfo));
}
return (MultitonExample)_multiton[instanceInfo];
}
}
public struct ConnectionInfo {
public String IPAddress;
public int Port;
}
I don't have a test app prepared to show you how this works. I do know of a good example though, Random Number Generators. It's best to use them in a Singleton Pattern because they're usually seeded with a current timestamp, if two random number generators are created too close together, they'll produce similar output. Instead, if two or more different places in your code needed a generator, they could use the same one which would result in more random output for both of them. This does bring up the question of multithreaded-ness and the Singleton/Multiton Patterns. If you're using the one of the patterns in a threaded application, make sure the type that you're working with is thread safe or there's bound to be some problems. With thread safe types, there shouldn't be a problem implementing either of these.
Design Pattern, Source Code
design pattern, singleton, multiton