ProblemYou have a data type that will be used by several clients. This data type will create and hold a reference to another object that takes a long time to create; this could be a database connection or an object that is made up of many internal objects, which also must be created along with their containing object. Rather than allow this data type to be instantiated many times by many different clients , you would rather have a single object that is instantiated only one time and used by everyone. SolutionThe following two code examples illustrate the two singleton design patterns . The first design always returns the same instance of the OnlyOne class through its GetInstance method: public sealed class OnlyOne { private OnlyOne( ) {} private static OnlyOne theOneObject = null; public static OnlyOne GetInstance( ) { lock (typeof(OnlyOne)) { if (theOneObject == null) { OnlyOne.theOneObject = new OnlyOne( ); } return (OnlyOne.theOneObject); } } public void Method1( ) {} public void Method2( ) {} } The second design uses only static members to implement the singleton design pattern: public sealed class OnlyStaticOne { private OnlyStaticOne( ) {} // Use a static constructor to initialize the singleton static OnlyStaticOne( ) {} public static void Method1( ) {} public static void Method2( ) {} } DiscussionThe singleton design pattern allows one and only one instance of a class to exist in memory at any one time. Singleton classes are useful when you need a single way of accessing a resource such as a database connection or a file on a network. Many times, manager objects are created as singletons. For example, an object pool manager most likely would be a singleton; this allows a single access point to the pool for the entire application. Several examples of the singleton class can be found in the FCL, such as the System.Diagnostics.Trace , System.Diagnostics.Debug , and System.IO.Path classes, to name a few. The OnlyOne class implements the singleton pattern by using a static field of the same type as its containing classthe OnlyOne type, in this caseand a common access point called GetInstance . The GetInstance method is called by the client code to obtain the one and only instance of the OnlyOne class. If there are no instantiated OnlyOne classes, a new one is created and returned. Once the OnlyOne object is created for the first time by the GetInstance method, a reference to it is placed in the theOneObject static field. This field contains a reference to the only OnlyOne object running in the application. Note that because static fields do not cross application domain boundaries, a single instance of the OnlyOne object is created for each application domain in a process. On successive calls to GetInstance , the OnlyOne object referenced by theOneObject field is returned. All access to the OnlyOne object is performed on the object returned by the GetInstance method. The default constructor for this class has its accessibility made private to prevent code from accidentally creating an instance of this class. Setting the default constructor to private and disallowing any nonprivate constructors in this class is critical to a good singleton pattern. If code were to accidentally create a second or third class of this type, your application code would then have more than one access point to a resource, or you might have more than one manager type object managing a set of objects. When setting the default constructor to private, or if there is no default constructor in your class, you should mark the class with the sealed keyword. This keyword prevents any class from inheriting from this class. If a class were to inherit from this class, and if this new class did not provide an explicit constructor, a default constructor would be provided by the compiler. This default constructor is written to automatically call the base class's default constructor. If the base class's default constructor is private, it is inaccessible to its subclasses. The compiler will catch this type of error, but it makes the code more readable and maintainable if the sealed keyword is used to mark a singleton class. The OnlyStaticOne class implements the singleton pattern in a much different way. This class makes exclusive use of static members to allow only one access point to this class's members (the use of the word "instance" would be misleading herestatic members do not operate on an actual instance of an object, but rather on the type itself). Similar to the previous singleton pattern example, this class is also marked as sealed, and it has a private default constructor. There are advantages and disadvantages to using each of these implementations of the singleton design pattern. The advantages of using the OnlyOne style are:
The disadvantages to this style are:
The advantages to using the OnlyStaticOne style of the singleton class are:
The disadvantages to this style are:
See AlsoSee the "sealed" keyword and "lock Statement" topic in the MSDN documentation. |