Singleton Design Pattern (Apex Design Patterns)

What is singleton?: Its a design pattern which restricts the instantiation of a class to one “single” instance only within a single transaction context.

Why Singleton?: minimizing object instantiation for improved performance and to mitigate impact of governor limits

Let’s discuss problem first then solution using singleton pattern-

Problem:

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

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

So in above example, if the record are inserted/updated more than 100, we will get governor limit issue since AccountDemoRecordType object instance is created every time time for each record.

Solution: There are many solutions to this problem but we will solve it using a pattern(Singleton here).

trigger AccountTrigger on Account (before insert, before update) {
    for(Account record : Trigger.new){
        AccountDemoRecordType rt = AccountDemoRecordType.getInstance();
	record.recordTypeId = rt.id;
    }
}
//Lazy loading Variant
public class AccountDemoRecordType {
    public String id {get;private set;}
    private AccountDemoRecordType(){
        // This could breach the governor limits on describes
        // if a trigger is executed in bulk
        id = Account.sObjectType.getDescribe()
         .getRecordTypeInfosByName().get('Demo').getRecordTypeId();
    }

    private static AccountDemoRecordType instance = null;

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

Using this approach, you can’t instantiate AccountDemoRecordType class using constructor. You can instantiate is only using getInstance method. Also, only one instance is created for AccountDemoRecordType class using getInstance method, so we will not be getting governor limit issue even if record size increases beyond 100.

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

    private static AccountDemoRecordType instance = new AccountDemoRecordType();

    public static AccountDemoRecordType getInstance() {
        return instance;
    }
}

Eager initialization variant can be used if cost of creating the instance is small.

Logger is the best example which is using singleton pattern.

For all Design Patterns, please refer this.

Published by Sandeep Kumar

He is a Salesforce Certified Application Architect having 11+ years of experience in Salesforce.

Leave a Reply