Friday, August 13, 2010

Design Problems with Singletons

Following is a design guideline for implementing the Singleton design pattern. This guideline is composed using some key computer science principles such as the Single Responsibility Principle, Liskov Substitution Principle, Dependency Inversion Principle, and KISS.
  1. There must be one and only one instance of this class. For example, there is one and only one instance of an application. Even in this case, Singleton pattern is not recommended. If there are two modes of this applications, polymorphism will be hard to use when using an Application Singleton. In this case, it is a mere coincidence that we need one instance of this object, but not a design requirement.
  2. This instance must never die. This means that this particular class needs to stay alive until the end of application life cycle.
  3. Creation of this object has to be done in a lazy way. This means that the application doesn’t care about when this object is created.
  4. This object must be responsible for creating itself. There are risks associated with coupling creation and business implementation of an object. This has to be judged carefully.
  5. This class will dispose of any unmanaged resources in a manual way. Since an instance of this class will be created lazily, but it will stay alive until the end of application life cycle, it has to dispose of unmanaged resources such as WCF channels, file and memory streams, etc. right after it is done using them.
  6. There will never be a need to create Mock and Dummy objects of this type. Singletons make testing difficult, and sometimes impossible. For example, Logger.Instance singleton cannot be substituted with a mock object because it creates itself.
  7. It is understood that this class will implement some thread safety since it could be accessed by a number of threads in the application.
There are ways of implementing the Singleton pattern with less code duplication and without violating the principles state above. The Dependency Injection pattern can be used to do this. Create a Dependency Injector (there are some open source options such as Unity, Ninject for .NET) to enforce the Singleton pattern. This way, the Singleton creation is defined only once in one place rather than in all classes via copy/paste.

0 comments:

Post a Comment