Contents

Introduction

This article describes how to implement a Singleton design pattern in Apex. The Singleton pattern attempts to solve the issue where you are repeatedly using an object instance but only wish to instantiate it once within a single transaction context. Common uses for this pattern include:

  • Global variables - whilst Apex does not support global variables across execution contexts, this pattern allows you to create an object instance that will only ever be instantiated once within an execution context.
  • Limiting Impact of Governor Limits - certain system objects and methods such as Apex Describes are subject to governor limits. The Singleton pattern allows repeated reference to these without breaching governor limits.
  • As an implementation to other patterns - other design patterns such as Facade are often implemented as Singletons

However, it's most common use is to create an object instance that's instantiated only once for the lifetime of that execution context.

For the parent page to this article, and for a full list of other design patterns, go to Apex Design Patterns.

Problem

Often developers can write inefficient code that can cause repeated instantiation of objects. This can result in inefficient, poorly performing code, and potentially the breaching of governor limits. This most commonly occurs in triggers, as they can operate against a set of records.

The following code shows an example of repeated code invocation that can result in a breach of governor limits:

The Trigger

trigger AccountTrigger on Account (before insert, before update) {
    for(Account record : Trigger.new){
        AccountFooRecordType rt = new AccountFooRecordType();
        ....
    }
}


The Class

public class AccountFooRecordType {
    public String id {get;private set;}
    public AccountFooRecordType(){
        // This could breach the governor limits on describes
        // if a trigger is executed in bulk
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
}

The trigger will cause a repeated execution of the sObject getDescribe() method, resulting in a breach of the total number of describes governor limit if the trigger operates against more than 100 records.

UML

Singleton.png

Implementation

In order to implement a Singleton pattern in Apex, the class must instantiate only a single instance and be globally accessible. It is implemented by:

  • Creating a class with a method that creates a new instance of the class if it doesn't already exist
  • If it already exists, then simply return a reference to that object

The following code sample demonstrates an implementation of the Singleton pattern to return a record type describe within a trigger:

The Trigger

trigger AccountTrigger on Account (before insert, before update) {
    for(Account record : Trigger.new){
        // Instantiate the record type using the singleton class
        AccountFooRecordType rt = AccountFooRecordType.getInstance();
        ....
    }
}

The Singleton Class

public class AccountFooRecordType {
    // private static variable referencing the class
    private static AccountFooRecordType instance = null;
    public String id {get;private set;} // the id of the record type

    // The constructor is private and initializes the id of the record type
    private AccountFooRecordType(){
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
    // a static method that returns the instance of the record type
    public static AccountFooRecordType getInstance(){
        // lazy load the record type - only initialize if it doesn't already exist
        if(instance == null) instance = new AccountFooRecordType();
        return instance;
    }
}

The above code demonstrates the following:

  • The getInstance() static method will only instantiate an instance of the class if it doesn't already exist in a lazy-initialization manner
  • The constructor and the instance variable for the class is private to make sure that it cannot be instantiated outside of the getInstance() method
  • The class defines a private, static instance of itself that can only be referenced via the getInstance() static method
  • The Id member stores the record Id of the record type and is initialized in the constructor

This allows the trigger to obtain a reference to the record type without breaching governor limits.

The following code sample shows how to use eager-initialization so that a new instance is always created when the class is instantiated.

The Singleton Class - Eager Initialization variant

public class AccountFooRecordType {
    // a static, final variable that initializes an instance of the class
    // as it's final, it will only be initialized once
    private static final AccountFooRecordType instance = new AccountFooRecordType();
    public String id {get;private set;}
    private AccountFooRecordType(){
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
    public static AccountFooRecordType getInstance(){
        // eager load of the class
        return instance;
    }
}

The instance of the class is instantiated as a final, static variable, which means that only one instance ever exists. This method is typically used if the cost of creating the instance is small.

Conclusion

The Singleton design pattern allows Apex code to repeatedly reference an object instance in an optimal manner, whilst mitigating the impact of governor limits.

See the Apex Design Patterns article for more design patterns.