The Singleton pattern is used for controlling the number of instances of a class (to one in
general). This is maybe the first, the most used and the easiest design pattern out there.
Scope : Object Lifetime / Per Class loader
Description
The Singleton pattern is a way for multiple objects to share a common object without having to know whether it already exists. It ensures that only one instance of a class is created. All objects that use an instance of that class use the same instance. There must be at least one instance of a class. Even if the methods of our class use no instance data or only static data, we may need an instance of the class for a variety of reasons. The one instance of a class must be accessible to all clients of that class. These classes usually involve the central management of a resource. The resource may be external, as is the case with an object that manages the reuse of database connections. The resource may be internal, such as an object that keeps an error count and other statistics for a compiler.Purpose
Some of the more common reasons are that we need an instance to pass a method of another class or that we want to access the class indirectly through an interface. There should be no more than one instance of a class. This may be the case because we want to have only one source of some information.Pros
Single point access to a single instance of a class, basically a sort of globally
accessible instance of the class
Instance control
Singleton prevents other objects from instantiating their own copies of the Singleton object, ensuring that all objects access the single instance.Flexibility
Because the class controls the instantiation process, the class has the flexibility to change the instantiation process.Memory Consumption
An object is cheap to create but takes up a lot of memory or continuously use other resources during its lifetime.Consequences
Dent to Java OOP concept (encapsulation/polymorphism)
The singleton class’sgetInstance
method encapsulates the creation policy for the singleton
class, so that classes that use a singleton class do not depend on the details of its instantiation.
Sub classing a singleton class is awkward and results in imperfectly encapsulated classes.
Constructor is not accessible
Other classes that want a reference to the one instance of the singleton class must get that instance by calling the class’sgetInstance
static method, rather than by constructing the instance
themselves.
Difficult to Test
Making a class a singleton can make it difficult to test its clients, as it’s impossible to substitute a mock implementation for a singleton unless it implements an interface that serves as its type.Instance Per Class Loader
Beware that this control ( controlling the number of instances of a class ) is available per class loader, and not for JVM, not to say more when thinking at distributed topologies.- This is because the final static instance variable being static is per class basis. As you know now, in a JVM you can have more than one class loader – meaning you can load the same Singleton implementing class more than once (once per class loader).
- Loading more than once the Singleton implementing class results in the possibility of having N instances controlled by the singleton per JVM, where N represents the number of the loads of the Singleton implementing class, so will need at least N class loaders.
Cluster Deployed Application
In a multiple JVM topology ( cluster deployed application ) special algorithms must be taken into consideration for controlling the number of instances of a class. These can be fine-tuned depending on the needs of the application requirements.Implementation
The Singleton pattern is relatively simple, since it involves only one class. A singleton
class has a static variable that refers to the one instance of the class we want to use.
The instance can be created when the class is loaded into memory or later on demand. We
should implement the class in a way that prevents other classes from creating additional
instances. That means ensuring that all of the class’s constructors are private.
Another approach of implementing singletons are simply make an enum type with one element. A single-element enum type is the best way to implement a singleton. We should provide a single accessor method in the class to access single instance.
Another approach of implementing singletons are simply make an enum type with one element. A single-element enum type is the best way to implement a singleton. We should provide a single accessor method in the class to access single instance.
Though the Singleton pattern involves a relatively simple solution, there are a surprising number of subtleties in its implementation.
Private Constructor
We must code the class in a way that prevents other classes from directly creating instances of the class. A way to enforce this is to declare the class’s constructors private. Be careful to declare at least one private constructor. If a class does not declare any constructors, then the Java compiler automatically generates a default public constructor.Lazy Instantiation
A common variation on the Singleton pattern occurs in situations where the instance of a Singleton may not be needed. We do not know whether the program will need to use the singleton instance until the first time that thegetInstance
method is called.
Allowing More Than One Instance
Another variation on the Singleton pattern stems from the fact that it has a class’s instantiation policy encapsulated in the class itself. Because the instantiation policy is encapsulated in the class’sgetInstance
method, it is possible to vary the creation policy. This sort of situation
can come up when we are using small, fixed individual objects to represent external resources and we want to
balance the load between them.
Concurrent GetInstance Calls
If there is any chance that multiple threads may call a singleton class’sgetInstance
method at the same time, then we will need to make sure that the
getInstance
method does not create multiple instances of the singleton class.
If two threads call the getInstance
method at the same time and there were no previous calls to
the getInstance
method, then both calls will see that the value of
myInstance is null
, and both calls will create an instance. We can avoid this by Synchronizing
the getInstance
method.
Declaring the getInstance method to be synchronized does add a small amount of overhead by
forcing every call to the getInstance method to get a synchronization lock before it proceeds.
We can also avoid this additional over head by providing an additional check on value of
myInstance before synchronized block and again a same check under synchronized block to avoid multiple
instance being created. This approach is known as dual check.
Create getInstance having dual check
Making Copies of a Singleton
- A singleton object is usually intended to be the only instance of its class. Even in the case in which we allow more than one instance of a singleton object, we generally want to ensure that creation of singleton objects is entirely under the control of the singleton class’s getInstance object. This means that we don’t want any other classes making copies of a singleton object.
- Singleton class should not implement the java.lang.Cloneable interface. It should not be possible for another class to make a copy by calling a singleton object’s clone method.
- Serialization is a mechanism that Java provides for converting the contents of objects into a stream of bytes. Deserialization is a mechanism that Java provides for converting a stream of bytes created by serialization to objects that have the same contents as the original objects.
- Serialization can be used to copy objects, but copying is not usually the intended use of serialization.
- Serialization is used to make objects persistent by writing them to a file as a stream of bytes. This allows persisted objects with the same contents to be recreated later on.
- Serialization is used to support remote procedure calls using RMI. RMI is used by EJB (Enterprise JavaBeans). RMI uses serialization to pass argument values to remote procedure calls and also to pass the return value back to a remote caller.
A Subtle Bug
- There is a rather subtle bug that can occur in implementations of the Singleton pattern. It can cause a singleton class to create and initialize more than one instance of itself over time. The problem occurs in programs that refer to a singleton class only through other classes that are dynamically loaded.
- This behavior can be a problem for singleton classes. If a singleton class is garbage-collected, it will be loaded again if there is another dynamic reference to it. After the class has been loaded a second time, the next request for its instance will return a new instance! This can produce unexpected results.
Implementation
Related pattern
We can use the Singleton pattern with many other patterns. In particular, it is often used with the Abstract Factory, Builder, and Prototype patterns.References
- http://stackoverflow.com
- http://www.javalobby.org
- Patterns in Java by Mark Grand
- Effective Java 2nd Edition by Joshua Bloch
Post a Comment
Post a Comment