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, it's possible and pretty easy with Apex. There can be different strategies to implement singleton in Apex (inspired by my Java days learning). Before that, the following are the prerequisites to make a class Singleton.
There can be a static public method in class that returns the “Single” instance. Popular names for it are “self()” and “getInstance()” OR one can declare a public static property with only a public get accessor and private set accessor. I will show this in a while.
A constructor should have the 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 a simple Apex Singleton strategy. I said it's “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 the Simple Apex singleton strategy is that it's not meant to be used in cases where singleton initialization requires some DML code to execute. For that scenario, we need to set up the class a 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 test methods are added at the end of each Singleton sample; this also shows how to use Singleton in client Apex Code.
Still, if you feel some gaps or have some queries, please feel free to ask in the comments.
Let’s Talk
Drop a note below to move forward with the conversation 👇🏻