Table of Contents
Introduction
Apex allows us to develop any custom solution. This post is an aggregate of common design patterns and associated best practices for Apex development. Knowing these patterns will not only help you achieve excellence in daily development but also will prepare you to rock any Developer interview.
Types of Design pattern
Singleton — minimizing object instantiation for improved performance and to mitigate the impact of governor limits
Strategy — defining a family of algorithms, encapsulating each one and making them interchangeable and selectable at runtime
Decorator — extending the functionality of a sObject in Apex
Bulk State Transition — efficiently tracking the change of a field value in a trigger and executing functionality based on this change
Composite — treating a group of objects in a similar manner to a single instance of that object
The Singleton Pattern
- Ensure a class has only one instance, and provide a global point of access to it.
- Encapsulated “just-in-time initialization” or “initialization on first use“.
Intent
The intent of the Singleton pattern is to provide only a single instance of the class and that instance can be used anywhere throughout the transaction.
In other words,
The application needs one, and only one, an instance of an object. Additionally, lazy initialization and global access are necessary.
Structure
Example
The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance.
The office of the President of the India is a Singleton. The Indian Constitution specifies the means by which a president is elected, limits the term of office, and defines the order of succession. As a result, there can be at most one active president at any given time. Regardless of the personal identity of the active president, the title, “The President of the India” is a global point of access that identifies the person in the office.
Credit – https://sourcemaking.com/design_patterns/singleton
What iT takes to develop Singleton pattern
- Public Property that needs to be accessed by developers/users
- Private Instance of the Apex Class
- Private constructor to run the code
- Public static method that a developer can refer to in the code
Problem Statement
Let’s say you are integrating the Stripe Payment gateway with Salesforce and need to send the data to Stripe on certain actions. For Example, Account Creation.
You have developed the following apex call as initial version
InItial Version - v1
public with sharing class SingletonClass {
public static void createPaymentInStripe(Payment__c payment) {
StripeConfig__c stripeConfig = new QueryFactory.QueryBuilder()
.selectFrom(StripeConfig__c.class)
.query()
.first();
// Make Stripe API Callout to create a Payment in Stripe using Http Class
}
public static void createCustomerInStripe(Account customer) {
StripeConfig__c stripeConfig = new QueryFactory.QueryBuilder()
.selectFrom(StripeConfig__c.class)
.query()
.first();
// Make Stripe API Callout to create a Customer in Stripe using Http Class
}
}
If you notice that, in the above code we are making the SOQL query for both the methods and there could be more methods. Now consider, that if there is bulk data then you will get into SOQL Governor Limit.
Let’s modify the code and have a separate method do make the SOQL Query
Modified - v2
public with sharing class SingletonClass {
public static StripeConfig__c queryConfig(){
StripeConfig__c stripeConfig = new QueryFactory.QueryBuilder()
.selectFrom(StripeConfig__c.class)
.query()
.first();
return stripeConfig;
}
public static void createPaymentInStripe(Payment__c payment) {
StripeConfig__c stripeConfig = queryConfig();
// Make Stripe API Callout to create a Payment in Stripe using Http Class
}
public static void createCustomerInStripe(Account customer) {
StripeConfig__c stripeConfig = queryConfig();
// Make Stripe API Callout to create a Customer in Stripe using Http Class
}
}
We have made the changes and kept the query in a separate method. However still if there are many records you will get into Governor Limit.
Let’s develop the same using the Singleton pattern.
Using Single Pattern
public with sharing class SingletonClass {
/* Create the private instance of SingletonClass */
private static SingletonClass instance;
/* Create the public varibale to store the StripeConfig__c */
public static StripeConfig__c stripeConfig;
/* Create a private constructor to prevent the creation of an instance of the class */
private SingletonClass() {
stripeConfig = new QueryFactory.QueryBuilder()
.selectFrom(StripeConfig__c.class)
.query()
.first();
}
/* create the publically available resource to get the instance of the class */
public static SingletonClass getInstance(){
if(instance == null){
instance = new SingletonClass();
}
return instance;
}
public static void createPaymentInStripe(Payment__c payment) {
SingletonClass.getInstance();
/* Stripe Configuration variable will become available here */
// Make Stripe API Callout to create a Payment in Stripe using Http Class
}
public static void createCustomerInStripe(Account customer) {
SingletonClass.getInstance();
/* Stripe Configuration variable will become available here */
// Make Stripe API Callout to create a Customer in Stripe using Http Class
}
}
In the above code, we have implemented the Singleton Pattern and now the instance will only be initialized once.
Check list
- Define a private static attribute in the “single instance” class.
- Define a public static accessor function in the class.
- Do “lazy initialization” (creation on first use) in the accessor function.
- Define all constructors to be protected or private.