Software Development, Product to Market
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use

Different Singleton Implementations

6/26/2013

0 Comments

 
‘Singleton’ is a fancy word for ‘global variable.’

​The intent of Singleton:
Ensure a class only has one instance, and provide a global point of access to it. - GOF
All singleton implementations offer NO public constructor but only private constructor to enforce non-instantiability. In Java, however, because a private constructor can still be accessed through a backdoor of using reflection, you want to add extra check in the private constructor to guard against reflection vulnerability (see examples below).

approach #1

Is this approach thread-safe? Yes.

Prior to Java 1.5 release, using initialization of a static final member field, there are primarily two ways of making a class singleton. One way is to make this static final member public and be initialized  when referenced:
public class Singleton{
  public static final Singleton INSTANCE = new Singleton(); // 1

  private Singleton(){

    if(INSTANCE != null) {  // 2
      throw new IllegalStateException("instance already created.");
    }

  }
}
The Singleton object is not created until Singleton.INSTANCE is referenced.

[1] Static variable INSTANCE will be initialized when Singleton.INSTANCE is referenced (requested).
[2] The extra check on whether INSTANCE is null or not in the private constructor is to guard against reflection attack which is how multiple instances may be instantiated is now prevented.

approach #2

Is this approach thread-safe? Yes.

Another way is to make this static final member private with a public static factory-method (getInstance()) to return the sole singleton instance:
public class Singleton{
  private static final Singleton INSTANCE = new Singleton();
  private Singleton(){
    if(INSTANCE != null) { 
      throw new IllegalStateException("instance already created.");
    }
  }
  public static Singleton getInstance(){
    return INSTANCE;
  }
}
The Singleton object is also not created until a call is made to the static getInstance() method to reference the static member field INSTANCE. 

One of the advantages of this factory-method approach over the first approach is that you can later change the implementation of getInstance() without clients needing to change the interface of calling it. For example, instead of returning a sole instance per classloader, your can extend to make getInstance() to return a sole instance per thread.

approach #3

Is this approach thread-safe? Yes.

Both approach #1 and #2 initialize a static field to ensure that the Singleton object is not created until Singleton.INSTANCE is referenced or when a call is made to the static getInstance() method. This is a good approach because such Singleton implementations are thread-safe when it comes to getting a reference to the Singleton instance. Otherwise, should you not initialize the static member field via declaration, you'll have to assure thread-safe via synchronization as in this approach:
public class Singleton{
  private final Singleton INSTANCE;


  private Singleton(){
    if(INSTANCE != null) { 
      throw new IllegalStateException("instance already created.");
    }
  }


  public static synchronized Singleton getInstance(){

    if (INSTANCE == NULL){
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }

  ...
}

Synchronization is costly. Although Double Checked Locking idiom was mentioned to make above costly synchronized block smaller to reduce overhead in a multi-threaded environment, but the double Checked Locking is not a safe programming construct due to the current Java memory model making it an anti-pattern.

approach #4

Is this approach thread-safe? Yes.
Both serializable and deserializable? Yes.

A forth and better way of implementing Singleton is to use a single-element Enum type (available in Java 1.6+). Enum constants (e.g. INSTANCE) are implicitly static and final so you can not change INSTANCE value once created. The constructor of enum in java must be private to hide it. Utilize it to wrap around the singleton object you'd like to assure singleton and return it.
public enum Singleton{ // 1
  INSTANCE; // instance vars, constructor

  private final Connection connection;

  private Singleton() { // 2
    connection = DB.getConnection();
​  }

  
// Static getter
  public static Singleton getInstance() { return INSTANCE; }  
​  
public Connection getConnection() { return connection; }
}
[1] enum is automatically Serializable according to its javadoc.
[2] Initialize the connection when enum (Singleton.INSTANCE) is referenced for the first time.

To get a reference to the singleton object, use  Singleton.getInstance() or Singleton.INSTANCE. To get the connection, do Singleton.INSTANCE.getConnection().

This single-element Enum provides an guarantee against multiple instantiation, and hold up pretty well in the face of sophisticated serialization or reflection attacks, making it the recommended approach of all approaches.

serializable singleton

Without extra consideration, most of the above approaches serializable does not make the deserialization back to a Singleton unless you add readResolve() implementation (more details see my Java Serialization post) to your serializable class so that when Singleton is deserialized, the returned object is a guaranteed singleton:
public class Singleton implements Serializable{
  ...  
  private Object readResolve() throws ObjectStreamException{ // 1
    return INSTANCE;
  }
  ...
}

[1] The readResolve method is called when ObjectInputStream has read an object from the stream and is preparing to return it to the caller. It should not be explicitly called other than by the deserialization runtime.

The "enum approach" does comes an guarantee against multiple instantiation without needing extra code, making it serializable singleton by default for free.

discussion

Some consider Singleton an anti-pattern because it couples your code with specific implementation.

Here's a scenario: Whenever a client retrieves a singleton's instance, that client becomes undesirably coupled with the fact that its supplier is a specific type of singleton. For example, in the following code snippet, the Client can no longer easily 'deploy' by swapping in a different kind of Deployer because the principle of "programming to an interface, not an implementation" is violated.
public class Client { 
  ...
  public void deploy(File targetFile) {
    Deployer.getInstance().deploy(this, targetFile); 
  }
  ...
}
Therefore, do not over use Singleton, consider to use Singleton only when
  • you need to have a global point of access to a single instance of a given class, and
  • every application ever needs only one instance of this class

summary

Accept synchronization, use a static field, or use enum to make Singleton thread-safe. Get away from Double Checked Locking idiom which is an antipattern. Do not overuse Singleton.

references

  • Java Enum Tutorial: 10 Examples of Enum in Java 
  • Design patterns in the real world
  • Singleton using enum
0 Comments



Leave a Reply.

    Categories

    All
    Algorithm
    Concurrency
    CQ
    Data Structure
    Design Pattern
    Developer Tool
    Dynamic Programming
    Entrepreneur
    Functional Programming
    IDE
    Java
    JMX
    Marketing
    Marklogic
    Memory
    OSGI
    Performance
    Product
    Product Management
    Security
    Services
    Sling
    Social Media Programming
    Software Development

    Feed Widget

    Archives

    May 2020
    March 2020
    April 2018
    March 2018
    February 2018
    December 2017
    March 2017
    November 2016
    June 2016
    May 2016
    April 2016
    October 2015
    September 2015
    August 2015
    September 2014
    July 2014
    June 2014
    May 2014
    March 2014
    January 2014
    December 2013
    November 2013
    October 2013
    September 2013
    August 2013
    July 2013
    June 2013

    RSS Feed

in loving memory of my mother  and my 4th aunt
Photos used under Creative Commons from net_efekt, schani, visnup, Dan Zen, gadl, bobbigmac, Susana López-Urrutia, jwalsh, Philippe Put, michael pollak, oskay, Creative Tools, Violentz, Kyknoord, mobilyazilar