I've been studying Design Patterns. A Singleton pattern is described as "minimizing object instantiation for improved performance and to mitigate impact of governor limits."
In the Technical Library doc Apex Design Patterns under Singleton, it says the following.
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.
In the implementation, it goes on to give an example of a trigger that calls a class that uses a describe call to instantiate a record type for an Account.
The Question:
Now that Governor Limits no longer exist on describe calls (describe call limits were 100 per execution context when article was written), other than speed from not having to make the additional calls, what will be the primary benefits in the context of Apex for using the Singleton Design pattern?
I can see where having a query or describe call having to only run once and then essentially being cached in a variable offers a lot of potential for speed advantages and reduced memory when processing code, but clearly the specific governor limits that previously were cited as drivers for using this pattern in an APEX context no longer exist on the platform.
Are there other governor limits that still exist where the Singleton pattern is of particular value or other use cases where it's especially advantageous or frequently used?
For reference:
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;
}
}