Monday, 22 February 2010

ColdFusion Head First Design Patterns: Singleton

Everyone's favorite, The Singleton Pattern, is probably the most overused and least well implemented design pattern.

There are at least seven different variations on the singleton implementation in Java, some are detailed in Head First Design Patterns, some are documented in Joshua Bloch's awesome book Effective Java, and some I've found along the way on the web.

Not all of the variations can be implemented in ColdFusion, but lets list them and pick the best one to code in CFML.

None of them can be implemented in ColdFusion, but lets list them and see why.

Lazily created Singleton with static factory method

Introduced as the first singleton example in Head First Design Patterns. It isn't thread safe.

public final class Singleton {

  private static Singleton instance;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (null == instance) {
      instance = new Singleton();
    }

    return instance;
  }
}

Synchronized lazily created Singleton with static factory method

Introduced as the second example in Head First, it is thread safe but uses a computationally expensive synchronized method.

public final class Singleton {

  private static Singleton instance;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (null == instance) {
      instance = new Singleton();
    }

    return instance;
  }
}

Eagerly created Singleton with static factory method

Detailed as an alternative to synchronizing the getInstance() method in Head First, and presented as a possible implementation in Joshua Bloch's Effective Java. Bloch goes on to note that this implementation and the following implementation can not be made serializable by just adding implements Serializable. All instance fields would need to be declared transient and a readResolve() method provided.

public final class Singleton {

  private static final Singleton INSTANCE = new Singleton();

  private Singleton() {
  }

  public static Singleton getInstance() {
    return INSTANCE;
  }
}

Eagerly created Singleton with public final field

Presented by Bloch as an alternative to the above implementation, it's main advantage is that the class definition clearly shows it is a singleton.

public final class Singleton {

public static final Singleton INSTANCE = new Singleton();

  private Singleton() {
  }
}

Double checked locking

The third and final example in Head First, only synchronizes the first time through the getInstance() method. This implementation of the singleton makes use of the volatile keyword. In Java versions 1.4 and earlier, volatile could allow improper synchonization, this implementation is not portable to older JVMs.

public final class Singleton {

  private volatile static Singleton instance;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (null == instance) {
      synchronized (Singleton.class) {
        if (null == instance) {
          instance = new Singleton();
        }
      }
    }

    return instance;
  }
}

The solution of Bill Pugh

The solution of Bill Pugh uses a nested class to be as lazy as possible, is thread safe without using synchronized or volatile, and is usable with all JVM versions.

public final class Singleton {

  private Singleton() {
  }

  private static class SingletonHolder {

    private static final Singleton INSTANCE = new Singleton();
  }

  public static Singleton getInstance() {
    return SingletonHolder.INSTANCE;
  }
}

Enum Type

Since version 1.5, Java has had support for enums. The final implementation in Effective Java uses an enumerated type with one element. This is equivalent to the public final field implementation but takes care of serialization automatically, and guarantees only a single instance.

public enum Singleton {

  INSTANCE;
}

From Effective Java:

"a single-element enum type is the best way to implement a singleton."

ColdFusion

ColdFusion doesn't support enum types or nested CFCs, so those are out straight away.

Lazily created Singleton with factory method

A lazily created Singleton fails to be initialized because the component can't see its own private constructor.

LazyFactoryMethod/Singleton.cfc

<cfcomponent output="false" >

  <cffunction access="private" returntype="Singleton" name="init">
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="Singleton" name="getInstance">
    <cfif NOT isDefined("VARIABLES.INSTANCE")>
      <cfset VARIABLES.INSTANCE = createObject("component", "Singleton").init()>
    </cfif>
  
    <cfreturn VARIABLES.INSTANCE>  
  </cffunction>
  
</cfcomponent>

Eagerly created Singleton with factory method

An eagerly created Singleton with a factory method goes in to a self referential loop and fills up the stack.

EagerFactoryMethod/Singleton.cfc

<cfcomponent output="false" >

  <cfset VARIABLES.INSTANCE = createObject("component", "Singleton").init()>

  <cffunction access="private" returntype="Singleton" name="init">
    <cfreturn THIS>
  </cffunction>

  <cffunction access="public" returntype="Singleton" name="getInstance">
    <cfreturn VARIABLES.INSTANCE>  
  </cffunction>
  
</cfcomponent>

Eagerly created Singleton with a public field

Same as with the previous eagerly created Singleton, a java.lang.StackOverflowError is thrown on instantiation.

EagerField/Singleton.cfc

<cfcomponent output="false" >

  <cfset THIS.INSTANCE = createObject("component", "Singleton").init()>

  <cffunction access="private" returntype="Singleton" name="init">
    <cfreturn THIS>
  </cffunction>

</cfcomponent>

So ColdFusion can't create real singletons, how bad does that suck?

Source Code