March 8, 2010

Apex Implementing Singleton design pattern

Singleton is pretty popular and one of the most simple design patterns. On many occasions we want an Apex class to have a single instance only. Fortunately its pretty easy and possible with Apex. Though there can be different strategies to implement singleton in Apex (inspired from my Java days learning). Before that following are the prerequisite to make a class Singleton.

  • There can be a static public method  in class that returns the “Single” instance. Popular names to it are “self()” and “getInstance()” OR one can declare a public static property with only public get accessor  and private set accessor. We will show this in a while.
  • Constructor should have access modifier “private”. This is a must because, it will restrict other apex classes from creating the instance directly.

As I said there can be many ways to implement Singleton,

Simple Apex Singleton Strategy

This strategy is for simple Apex Singleton strategy. I said its SIMPLE because in this implementation we are assuming there will be no DML inside the constructor or static block. Here is the implementation

public class ApexSimpleSingleton {
  /*
    Note: this is the static handle to the single class reference.
    Its set accessor is made private to dis-allow any modifications to the reference 
  */
  public static ApexSimpleSingleton self {get; private set;}
  
  static {
    // Static block used for transparent Singleton setup. the "self" static variable
    // will be ready as soon as class will be loaded in memory.
    self = new ApexSimpleSingleton();  
  }
  
  // NOTE: the constructor is marked "PRIVATE"
  // so that no Apex code outside this class can create 
  // the instance
  private ApexSimpleSingleton() {
    // Do all the non DML initalization here
  }
  
  // ..
  // ....
  // Rest of the code can be instance level methods that
  // provide access through the single handle
    
  public void sayHello() {
    System.debug('Hello World');
  }

  // TEST METHOD
  public static testmethod void testSingleton() {
    //Will print "Hello World" on console.
    ApexSimpleSingleton.self.sayHello();
  }
}
Advanced Apex Singleton Strategy

The limitation of Simple Apex singleton strategy is its not meant to be used in case Singleton initialization requires some DML code to execute. For that scenario we need to setup the class little differently. Here is the sample

  public class ApexAdvancedSingleton {
  
  //Note: this is the static handle to the single class reference.
  //Its completely hidden to outside world. PRIVATE access modifier used   
  private static ApexAdvancedSingleton self;
  
  // NOTE: the constructor is marked PRIVATE
  // so that no Apex code outside this class can create the instance
  private ApexAdvancedSingleton() {
    // Do all the non DML initalization here
  }
  
  /*
    This static method will be the only way to get the Single 
    instance of this class.
  */
  public static ApexAdvancedSingleton getInstance() {
    // "self" is NOT NULL, that means we already did 
    // required initalization, so just return.
    if (self != null) return self;
      
      // Create the single instance now. 
      self = new ApexAdvancedSingleton();
      
      // All the DML Stuff to do the required one time setup. For example
      // you can use this code to create Org Wide custom settings 
      // if they don't exist.
      // ........................
      // ................................
      // ........................
      
      return self;
  }  
  
  // ..
  // ....
  // Rest of the code can be instance level methods that
  // provide access through the single handle
  
  public void sayHello() {
    System.debug('Hello World');
  }

  // TEST METHOD
  public static testmethod void testSingleton() {
    //Will print "Hello World" on console.
    ApexAdvancedSingleton.getInstance().sayHello();
  }
}

Lots of inline code comments to make this more readable and self understandable. Apex testmethods are added at end in each Singleton sample, this also shows how to use Singleton in client Apex Code.

Still if you feel some gap or have some queries, please feel free .. :)