Singleton (structural pattern) is primarily designed to limit the creation of objects of a given class to one instance and provide global access to it. It owes its origin to
C ++, where it played the role as the successor to the global variable used by the preprocessor. This pattern arouses a lot of controversy - seemingly simple, easy to implement, but badly used is a popular anti-pattern. This happens when its role is reduced to a global variable without considering the use context.
Singleton can be used where there should be only one shared instance of the class.
Singleton is created based on a private constructor that prevents to extend the class. In addition to managing its life cycle, it plays the role of business logic, which violates the principle of
SRP - a single responsibility. What’s more, it breaks the principle of
OCP - open / closed, which says that classes should be open to extension but closed to modifications.
Singleton makes testing difficult because before calling the tests, properly initialization of object must be provided. Due to the architecture of the
Singleton is not a recommended pattern in most cases.
Singleton Mutable can lose its state when the system needs to release the memory resources. Whereas
Singleton Immutable can often be replaced with
Utility classes (with static methods).
This pattern is used in accessing
SharedPreferences. Also a popular practice is to implement for objects such as
Logger or data access APIs, eg:
There are many implementations of this pattern. One of the simplest is based on initializing the object through the public
getInstance method only when it is first called. The constructor is invisible from outside the class.
The following listing shows the simplest implementation of
Singleton. However, it causes problems in a multi-threaded environment.
Double checking and locking should be used for
Singleton in multithreaded applications.
The optimal solution is
Singleton Holder, which ensures lazy creation of instances and does not require synchronization.
The application is designed to store and display user data. Access to data should be possible from different places of application. To solve the problem
SharedPreferences (which allows to store application settings) can be used. Read access and write access is provided by the class instance, and these operations are independent of this instance. Therefore, there is probably no need to store multiple
SharedPreferences instances in memory. Access to application settings can be used in many places, therefore the use of the
Singleton pattern seems to be justified.
SharedPreferences implicitly uses the
Singleton pattern. The following listing presents its explicit implementation.
The proper use of
Singleton is the use of the
Dagger 2 framework, implementing the ‘Injection of dependencies’ pattern.