All About Apex Design Patterns
Why Design Patterns?
Design patterns provide a general reusable solution for the common problems that occur in software design or data modules.
Design patterns are universal problem-solving strategies in software design, independent of any specific programming language, that address common challenges. This shows that design pattern is an idea, not a particular implementation.
You can make your code more maintainable, flexible and reusable by using design patterns.
In your project, it’s not mandatory to always implement design patterns. This gives us an idea that Design patterns are not meant for project development. It is meant for common problem-solving. Whenever there is a need, you must implement a suitable pattern to avoid any problems in future. To use a correct design pattern, try to understand the design patterns and their purpose. By understanding the design pattern's purpose and work, you will be able to pick the right one. As trusted salesforce consulting partners, we would like to highlight how we can implement the Apex design pattern in the salesforce. Let’s get into the details.
Common Design Patterns are listed below:
1) Singleton:
It minimizes object instantiation for
- Improved performance
- To mitigate impact of governor limits
Its primary application is to create a single instance of an object that remains instantiated throughout the entire lifespan of the execution context.
Developers frequently design inefficient code that causes objects to be instantiated several times. This can result in poorly performing codes and potentially breaching of governor limits. There are 2 ways to deal with this – Lazy Initialization and Eager Initialization.
Lazy Initialization:
To implement the Singleton pattern in Apex, the class should have a private constructor to prevent external instantiation and a static method to access the single instance globally. It is implemented by
adding a method to a class that creates a new instance of the class if one does not already exist.
If the object already exists, simply return a reference to it.
Step by Step implementation:
- In a lazy initialization, the getInstance() static function will only create an instance of the class if it does not already exist.
- The constructor and the instance variable are both private to prevent it from being instantiated outside of the getInstance() method.
- The class declares a private, static instance of itself that may only be accessed using the static function getInstance().
Sample Code:
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837ca67_1721474179.png)
Eager Initialization:
Only one instance of the class is ever created because it is instantiated as a final, static variable. If the cost of creating the instance is low, this method is usually employed.
A Singleton design pattern enables Apex code to efficiently reference an object instance while avoiding the effects of governor constraints.
Step by Step implementation:
- Create a private static member variable
- Create a public method getInstance()
- Return the instance from the method if already instantiated or create instance.
- Make the constructor private
Sample Code:
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837cc34_1721474179.png)
2) Strategy:
The strategy pattern, sometimes referred to as the policy pattern, addresses the need for offering multiple solutions to a particular problem, enabling the selection of one at runtime.
The strategy design pattern is the one that allows an algorithm's behavior to be chosen at run time. The strategy design pattern is employed to define a collection of algorithms that can be utilized interchangeably to address a common problem. Encapsulations allow for distinct logic per algorithm, but all algorithms are interchangeable at run time. Individual implementations are done at derived classes, whereas an interface provides abstraction.
This design pattern is suitable for scenarios where you intend to execute an operation with a shared objective, but there can be multiple approaches or methods to accomplish that objective. All these approaches can be chosen by the client at run-time.
Components of Strategy Design Pattern:
- Client - This acts as the entry point for the strategy pattern.
- Context - This is where the decision is made at runtime to determine the appropriate strategy.
- Interface Strategy - An interface that specifies a collection of methods to be implemented by concrete strategy classes.
- Concrete Strategy - A collection of class implementations that adhere to the specifications outlined in the Strategy Interface. Each concrete strategy class encapsulates distinct logic specific to its implementation.
For instance, let's say in the account detail page, you want to display the current temperature of the city where the office is located. Depending on the country or state, you may require gathering temperature information from various websites. However, the ultimate objective remains consistent in displaying the temperature. Propose a solution to retrieve the current temperature for an account. Temperature data will be gathered from various freely available Weather APIs based on geography. The design should be scalable and adaptable to accommodate future Weather APIs.
Step by Step Implementation:
- Create an Interface -> Parent
- Create implementation classes -> ChildOne, ChildTwo
- Create a service class & instantiate the interface instance with the implementation class as per the conditions-> AddChildPropertiesWrapper
- Call the methods of service class from any client. In this method, we call the child classes to distribute properties without needing to know about the parent.
Sample Code:
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837cdd0_1721474179.png)
3) Decorator:
We've all encountered situations where we need temporary fields just for calculations or displaying information in the user interface, however we do not wish to store that within the information or specifically within the object. To unravel this kind of downside, we've a decorator style pattern, that permits a user to feature new practicality to an existing object while not modifying its internal structure.
This pattern establishes a decorator category that envelops the initial category while preserving the same category methodology signature, thereby offering additional functionalities.
Below are several use cases, wherever we can use this style pattern -
- We have a list of records and want to perform some action on specific records. While we want to perform the same action on each record, we're looking at it from a perspective of what the user sees and interacts with, if we can give some checkboxes in order that the user can choose multiple records within the table and perform an equivalent operation on all the chosen records. We can show checkbox against every row, but we will not store that check-box info at the item level, this is just for Visual Force pages.
- Another example is, I need to show an inventory of Accounts with completely different currencies which require to be evaluated for a brief purpose. We can achieve this by adding extended options within the decorator category, and then it can be used on any VF page, Aura/LWC, to indicate the values in numerous currencies.
Step by Step Implementation:
- Create a Decorator class SquareCubeCalculator that wraps the Math__c for the extended functionalities.
- Fetch the object data and create a wrapper of it with custom extended functionalities.
- In the object level i.e. Math__c we are not storing the calculated squares and cubes, rather we are calculating the square and cubes and showing them on the Visualforce page.
Sample Code:
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837d121_1721474179.png)
Visual Force page – showAllSquaresCubes
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837d32a_1721474179.png)
4) Facade:
The basic role of the Facade design is to give an easier connecting point to a complex class. This keeps away from redundant code and increments practicality.
Frequently, the execution of a specific class requires various lines of code or is perplexing in nature. Assuming a similar code is repeated on numerous occasions across various pieces of the application, then, at that point, this will corrupt viability.
Basic purpose of making this design pattern included are:
- Simplifying the execution of an Apex Web Service Proxy class In Force.com, probably the greatest illustration of this is the execution of Web Service callouts. The produced Apex code frequently requires complex code, for example, setting timeout values, setting the target host as well as arrangement of the different information sources and parsing of the callout results.
- Let's say a specific organization provided a WSDL for a certain purpose. The consumer converted the WSDL into classes. Later, the same organization provided a second WSDL for another purpose. The consumer again converted the WSDL into a class. Now, If we look at the code, we will see that most of the code related to the endpoint configuration is the same. At this point, we can use the Facade approach to reuse the code. To do this, we will create a facade class and combine the code of the two services into one.
The Facade design pattern in Apex enhances code maintainability by streamlining the execution of complex classes through a simplified facade class.
5) Composite:
Definition:
It's a structural design pattern that merges into a tree structure where each node in a tree is a home of multiple objects.
Consumer can treat each container, a single object behaving the same way as that of its inner objects
This could look perplexing at first time, yet we could endeavor to get a handle on this with a model.
Composite is a foundational layout design that allows you to create objects into tree designs and afterward work with these designs as though they were individual items.
Composite plan design treats every hub in two ways:
1) Composite - Composite means it can have different articles beneath it.
2) leaf - leaf implies it has no items beneath it.
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837d4d4_1721474179.png)
Why Composite Design Pattern?
The Composite pattern lets you run a function or a method or a behavior recursively over all components of an object tree.
The best advantage of this approach is that you don't have to think often about the concrete classes of objects that make the tree. You don't have to know whether an object is a basic item or a complex box.
The Composite design pattern can be used to idolize an expression in Apex regardless of expression complexity, whilst mitigating the impact of governor limits that result from recursions.
6) Bulk State Transition:
The Bulk State Transition design pattern is a versatile pattern in Apex which is used to execute bulk actions on one or more records by responding to changes in their states. This pattern enables developers to efficiently process large datasets and apply specific actions based on the state changes of each record. It is used mostly with triggers.
Let's say whenever an opportunity is closed, we want an order to be created.
Step by Step Implementation:
We will implement the Bulk State Transition pattern utilizing two components:
- A trigger that calls a helper class method that creates a filtered list of eligible records that have changed state
- The helper class method then performs the logic on the list of eligible records in bulk
Sample Code:
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837d5f6_1721474179.png)
![All About Apex Design Patterns](https://theblueflamelabs.com/uploads/blog_posts/50/section/img_669b9c837d740_1721474179.png)
In conclusion to this blog post, above mentioned are some of the Apex Design Patterns which can be used to address common problems with general reusable solutions which makes your code more scalable, maintainable and modular.
Blueflame Labs, Salesforce implementation partners can help you with Apex design patterns. Get in touch to discuss it with our Salesforce experts.
Recent Blogs
![NetSuite Advanced Revenue Management (Essential)](https://theblueflamelabs.com/uploads/blog_posts/62/img_66d9f4c0a5caa_1725560000.jpg)
NetSuite Advanced Revenue Management (Essential)
Read More![Mastering Shipment Tracking with Zenkraft (Bringg)](https://theblueflamelabs.com/uploads/blog_posts/61/img_66d5685948fed_1725261913.jpg)
Mastering Shipment Tracking with Zenkraft (Bringg)
Read More![Integrating Form Titan with Salesforce](https://theblueflamelabs.com/uploads/blog_posts/60/img_66d0a4a5d31e1_1724949669.jpg)
Integrating Form Titan with Salesforce
Read More![Leveraging Rootstock ERP for your Purchase Orders & Authorizations](https://theblueflamelabs.com/uploads/blog_posts/59/img_66cc7c01b11c2_1724677121.jpg)
Leveraging Rootstock ERP for your Purchase Orders & Authorizations
Read More![A Guide to NetSuite Bank Reconciliation](https://theblueflamelabs.com/uploads/blog_posts/58/img_66c4aea09c0c8_1724165792.jpg)
A Guide to NetSuite Bank Reconciliation
Read More![Master Google Tag Manager & Google Analytics 4](https://theblueflamelabs.com/uploads/blog_posts/57/img_66bb74bb1488c_1723561147.jpg)
Master Google Tag Manager & Google Analytics 4
Read More![Step-by-Step Guide to Salesforce Data Migration](https://theblueflamelabs.com/uploads/blog_posts/56/img_66b5fad2bef1d_1723202258.jpg)
Step-by-Step Guide to Salesforce Data Migration
Read More![High-Performance APIs with .NET 8](https://theblueflamelabs.com/uploads/blog_posts/55/img_66b2294080154_1722952000.jpg)
High-Performance APIs with .NET 8
Read More