Salesforce Apex is a strongly-typed, object-oriented programming language that allows developers to execute flow and transaction control statements on the Salesforce platform. Many traditional design patterns can be used in Apex, but there are also patterns that have gained prominence specifically due to the unique aspects of the Salesforce platform.
Here’s a list of some of the more commonly used design patterns in Salesforce Apex, along with an example and a brief description of each:
- Singleton Pattern
- Description: Ensures that a class has only one instance and provides a global point to access it.
- Example:
public class SingletonClass { private static SingletonClass instance; private SingletonClass() {} public static SingletonClass getInstance() { if(instance == null) { instance = new SingletonClass(); } return instance; } }
- Factory Pattern
- Description: Provides an interface for creating an object but allows subclasses to alter the type of objects that will be created.
- Example:
public interface Shape { void draw(); } public class Circle implements Shape { public void draw() { System.debug('Drawing a circle'); } } public class ShapeFactory { public static Shape getShape(String shapeType) { if (shapeType == 'Circle') { return new Circle(); } return null; } }
- Bulk State Transition Pattern
- Description: Useful for maintaining the state of an object when dealing with bulk operations. It prevents governor limit issues.
- Example: When updating multiple records and needing to transition them through different states, one can create an object-oriented model to encapsulate the state transitions for each record.
- Selector Pattern
- Description: It separates the logic of querying data from the database and returns it in a structured way.
- Example:
public class AccountSelector { public List<Account> getActiveAccounts() { return [SELECT Id, Name FROM Account WHERE IsActive__c = TRUE]; } }
- Service Pattern
- Description: Provides a clear layer for business logic operations, ensuring that controllers or triggers are not cluttered with too much logic.
- Example:
public class AccountService { public void deActivateAccount(Account acc) { acc.IsActive__c = false; update acc; } }
- Unit Of Work Pattern
- Description: Manages a list of sObject records that need to be operated on (inserted, updated, deleted, etc.) and commits them all at once.
- Example: Can be seen in the FinancialForce Apex Common library, which provides an implementation for the Unit Of Work pattern.
- Domain Layer Pattern
- Description: It encapsulates the business logic and rules for a specific object or related group of objects.
- Example: It could involve validation rules, calculations, or any other logic that is relevant to the object’s domain.
- Trigger Framework/Handler Pattern
- Description: Separates the trigger’s logic into a handler class to ensure the trigger remains clean and follows a single responsibility principle.
- Example:
trigger AccountTrigger on Account (before insert) { AccountTriggerHandler.handleBeforeInsert(Trigger.new); } public class AccountTriggerHandler { public static void handleBeforeInsert(List<Account> newAccounts) { // Logic here } }
These are just some of the more commonly used design patterns in Salesforce Apex. When developing on the Salesforce platform, it’s beneficial to be familiar with these patterns to write scalable, maintainable, and efficient code.