Trigger Factory Pattern

Create an interface ITrigger as following

public interface ITrigger {
    /**
     * bulkBefore
     *
     * This method is called prior to execution of a BEFORE trigger. Use this to cache
     * any data required into maps prior execution of the trigger.
     */
    void bulkBefore();
    
    /**
     * bulkAfter
     *
     * This method is called prior to execution of an AFTER trigger. Use this to cache
     * any data required into maps prior execution of the trigger.
     */
    void bulkAfter();
    
    /**
     * beforeInsert
     *
     * This method is called for records during a BEFORE
     * trigger. Never execute any SOQL/SOSL etc in this and other iterative methods.
     */
    void beforeInsert(List newlstObj); 
    /**
     * beforeUpdate
     *
     * This method is called for records to be updated during a BEFORE
     * trigger.
     */
    void beforeUpdate(List newlstObj,List oldlstObj,Map newMapObj, Map oldMapObj);

    /**
     * beforeDelete
     *
     * This method is called for records to be deleted during a BEFORE
     * trigger.
     */
    void beforeDelete(List oldlstObj,Map oldMapObj);

    /**
     * afterInsert
     *
     * This method is called  for records inserted during an AFTER
     * trigger. Always put field validation in the 'After' methods in case another trigger
     * has modified any values. The record is 'read only' by this point.
     */
    void afterInsert(List newlstObj,Map newMapObj);

    /**
     * afterUpdate
     *
     * This method is called for records updated during an AFTER
     * trigger.
     */
    void afterUpdate(List newlstObj,List oldlstObj,Map newMapObj, Map oldMapObj);

    /**
     * afterDelete
     *
     * This method is called for records deleted during an AFTER
     * trigger.
     */
    void afterDelete(List oldlstObj,Map oldMapObj);

    /**
     * andFinally
     *
     * This method is called once all records have been processed by the trigger. Use this 
     * method to accomplish any final operations such as creation or updates of other records.
     */
    void andFinally();
}

Create TriggerException class as following
public class TriggerException extends Exception {}

Create TriggerFactory class

public  class TriggerFactory
{
    /**
     * Public static method to create and execute a trigger handler
     *
     * Arguments:   Schema.sObjectType soType - Object type to process (SObject.sObjectType)
     *
     * Throws a TriggerException if no handler has been coded.
     */
    public static void createHandler(Schema.sObjectType soType)
    {
        // Get a handler appropriate to the object being processed
        ITrigger handler = getHandler(soType);
        // Make sure we have a handler registered, new handlers must be registered in the getHandler method.
        if (handler == null)
        {
            throw new TriggerException('No Trigger Handler registered for Object Type: ' + soType);
        }
        // Execute the handler to fulfil the trigger
        execute(handler);
    }
    
    /**
     * private static method to control the execution of the handler
     *
     * Arguments:   ITrigger handler - A Trigger Handler to execute
     */ 
    private static void execute(ITrigger handler)
    {
        // Before Trigger
        if (Trigger.isBefore)
        {
            // Call the bulk before to handle any caching of data and enable bulkification
            handler.bulkBefore();
            // Iterate through the records to be deleted passing them to the handler.
            if (Trigger.isDelete) {
                handler.beforeDelete(trigger.old,trigger.oldMap);
            }
            // Iterate through the records to be inserted passing them to the handler.
            else if (Trigger.isInsert) {
                handler.beforeInsert(trigger.new);
            }
            // Iterate through the records to be updated passing them to the handler.
            else if (Trigger.isUpdate)
            {
                handler.beforeUpdate(trigger.new,trigger.old,trigger.newMap,trigger.oldMap);
            }
        }
        else
        {   
            // Call the bulk after to handle any caching of data and enable bulkification
            handler.bulkAfter();
            // Iterate through the records deleted passing them to the handler.
            if (Trigger.isDelete) {
                handler.afterDelete(trigger.old,trigger.oldMap);
            }
            // Iterate through the records inserted passing them to the handler.
            else if (Trigger.isInsert) {
                handler.afterInsert(trigger.new,trigger.newMap);
            }
            // Iterate through the records updated passing them to the handler.
            else if (Trigger.isUpdate) {
                handler.afterUpdate(trigger.new,trigger.old,trigger.newMap,trigger.oldMap);
            }
        }
        
        // Perform any post processing
        handler.andFinally();
    }
    
    /**
     * private static method to get the appropriate handler for the object type.
     * Modify this method to add any additional handlers.
     *
     * Arguments:   Schema.sObjectType soType - Object type tolocate (SObject.sObjectType)
     *
     * Returns:     ITrigger - A trigger handler if one exists or null.
     */     
    public static ITrigger getHandler(Schema.sObjectType soType)
    {
        if (soType == Contact.sObjectType){
            return new ContactTriggerHandler();            
        }
        return null;
    }
}

ContactTriggerHandler is a class that implements ITrigger interface.

Now create only one trigger on a object. Following example shows a trigger created on Contact object.

trigger ContactTrigger on Contact (after delete, after insert, after undelete, after update, before delete, before insert, before update) {    
    TriggerFactory.createHandler(Contact.sobjectType);  
}

Published by Sandeep Kumar

He is a Salesforce Certified Application Architect having 11+ years of experience in Salesforce.

2 thoughts on “Trigger Factory Pattern

Leave a reply to Sandeep Kumar Cancel reply