Singleton Pattern implements in Java

Implementing Singleton Pattern


1. General Steps
To implement this design pattern we need to consider the following 4 steps:
Step 1: Provide a default Private constructor
public class SingletonObjectDemo {

 // Note that the constructor is private
 private SingletonObjectDemo() {
  // Optional Code
 }
}


Step 2: Create a Method for getting the reference to the Singleton Objectpublic class SingletonObjectDemo {

 private static SingletonObject singletonObject;
 // Note that the constructor is private
 private SingletonObjectDemo() {
  // Optional Code
 }
 public static SingletonObjectDemo getSingletonObject() {
  if (singletonObject == null) {
   singletonObject = new SingletonObjectDemo();
  }
  return singletonObject;
 }
}

 


     We write a public static getter or access method to get the instance of the Singleton Object at runtime. First time the object is created inside this method as it is null. Subsequent calls to this method returns the same object created as the object is globally declared (private) and the hence the same referenced object is returned.

Step 3: Make the Access method Synchronized to prevent Thread Problems.

public static synchronized SingletonObjectDemo getSingletonObject()

It could happen that the access method may be called twice from 2 different classes at the same time and hence more than one object being created. This could violate the design patter principle. In order to prevent the simultaneous invocation of the getter method by 2 threads or classes simultaneously we add the synchronized keyword to the method declaration

Step 4: Override the Object clone method to prevent cloning

We can still be able to create a copy of the Object by cloning it using the Object’s clone method. This can be done as shown below

SingletonObjectDemo clonedObject = (SingletonObjectDemo) obj.clone();

This again violates the Singleton Design Pattern's objective. So to deal with this we need to override the Object’s clone method which throws a CloneNotSupportedException exception.

public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}

The below program shows the final Implementation of Singleton Design Pattern in java, by using all the 4 steps mentioned above.class SingletonClass {

 private static SingletonClass singletonObject;
 /** A private Constructor prevents any other class from instantiating. */
 private SingletonClass() {
  //  Optional Code
 }
 public static synchronized SingletonClass getSingletonObject() {
  if (singletonObject == null) {
   singletonObject = new SingletonClass();
  }
  return singletonObject;
 }
 public Object clone() throws CloneNotSupportedException {
  throw new CloneNotSupportedException();
 }
}

public class SingletonObjectDemo {

 public static void main(String args[]) {
  //  SingletonClass obj = new SingletonClass();  
                //Compilation error not allowed
  SingletonClass obj = SingletonClass.getSingletonObject();
  // Your Business Logic
  System.out.println("Singleton object obtained");
 }
}

2. Implemetion principles

(1).The solution of Bill Pugh

This is the recommended method. It is known as the initialization on demand holder idiom and is as lazy as possible. Moreover, it works in all known versions of Java. This solution is the most portable across different Java compilers and virtual machines.

The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile and/or synchronized).
 public class Singleton {
   // Protected constructor is sufficient to suppress unauthorized calls to the constructor
   protected Singleton() {}
 
   /**
    * SingletonHolder is loaded on the first execution of Singleton.getInstance()
    * or the first access to SingletonHolder.INSTANCE , not before.
    */
   private static class SingletonHolder {
     private final static Singleton INSTANCE = new Singleton();
   }
 
   public static Singleton getInstance() {
     return SingletonHolder.INSTANCE;
   }
 }


(2).Traditional simple way

Just like the one above, this solution is thread-safe without requiring special language constructs, but it lacks the laziness. The INSTANCE is created as soon as the Singleton class loads. That might even be long before getInstance() is called. It might be (for example) when some static method of the class is used. If laziness is not needed or the instance needs to be created early in the application's execution, this (slightly) simpler solution can be used:
 public class Singleton {
   public final static Singleton INSTANCE = new Singleton();
 
   // Protected constructor is sufficient to suppress unauthorized calls to the constructor
   protected Singleton() {}
 }

Sometimes the static final field is made private and a static factory-method is provided to get the instance. This way the underlying implementation may change easily while it has no more performance-issues on modern JVMs.


(3).Java 5 solution

If and only if the compiler used is Java 5 (also known as Java 1.5) or newer, AND all Java virtual machines the application is going to run on fully support the Java 5 memory model, then (and only then) the volatile double checked locking can be used (for a detailed discussion of why it should never be done before Java 5 see The "Double-Checked Locking is Broken" Declaration):
 public class Singleton {
   private static volatile Singleton INSTANCE;
 
   // Protected constructor is sufficient to suppress unauthorized calls to the constructor
   protected Singleton() {}
 
   public static Singleton getInstance() {
      if (INSTANCE == null) {
         synchronized(Singleton.class) {
           if (INSTANCE == null)
             INSTANCE = new Singleton();
         }
      }
      return INSTANCE;
   }
}

Allen Holub (in "Taming Java Threads", Berkeley, CA: Apress, 2000, pp. 176–178) notes that on multi-CPU systems (which are widespread as of 2007), the use of volatile may have an impact on performance approaching to that of synchronization, and raises the possibility of other problems. Thus this solution has little to recommend it over Pugh's solution described above.


(4).The Enum-way

In the second edition of his book "Effective Java" Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton" for any Java that supports enums. The use of an enum is very easy to implement and has no drawbacks regarding serializable objects, which have to be circumvented in the other ways.
 public enum Singleton {
   INSTANCE;
 }

posted on 2008-12-03 23:46 Daniel Liu 阅读(184) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

留言簿

文章档案(4)

最新随笔

搜索

最新评论