第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰。
十七篇链接:salesforce 零基础学习(十七)Trigger用法
有的时候对于sObject的trigger处理复杂的情况下,比如一个sObject的before update要实现功能1,2.....n功能情况下,Handler中需要在before update写实现功能1--n的代码。然而有些时候,我们在执行update情况下只需要让他触发功能i的功能代码,使用上述Handler方法也可以搞定,只不过处理起来比较尴尬,此篇针对trigger中对于不同业务分成模块进行处理。
一.Triggers基类
Triggers基类主要有以下内容:
1.枚举:封装的枚举包含了Trigger中的所有情况;
2.Handler接口:此接口中声明了一个方法handle,所有实现此接口的类都需要重写次方法;
3.bind方法,用于绑定事件以及实现Handler接口的类,即绑定的事件会使用实现Handler接口的类进行业务逻辑处理;
4.execute方法,用于执行triggers中绑定的Handler。
代码如下:
1 public class Triggers {
2
3 public enum Evt
4 {
5 AfterDelete,
6 AfterInsert,
7 AfterUndelete,
8 AfterUpdate,
9 BeforeDelete,
10 BeforeInsert,
11 BeforeUpdate
12 }
13
14
15 public interface Handler
16 {
17 void handle();
18 }
19
20 Map<String, List<Handler>> eventHandlerMapping = new Map<String, List<Handler>>();
21
22 public Triggers bind(Evt event, Handler eh)
23 {
24 List<Handler> handlers = eventHandlerMapping.get(event.name());
25 if (handlers == null)
26 {
27 handlers = new List<Handler>();
28 eventHandlerMapping.put(event.name(), handlers);
29 }
30 handlers.add(eh);
31 return this;
32 }
33
34 public void execute()
35 {
36 Evt ev = null;
37 if(Trigger.isInsert && Trigger.isBefore)
38 {
39 ev = Evt.beforeinsert;
40 }
41 else if(Trigger.isInsert && Trigger.isAfter)
42 {
43 ev = Evt.afterinsert;
44 }
45 else if(Trigger.isUpdate && Trigger.isBefore)
46 {
47 ev = Evt.beforeupdate;
48 }
49 else if(Trigger.isUpdate && Trigger.isAfter)
50 {
51 ev = Evt.afterupdate;
52 }
53 else if(Trigger.isDelete && Trigger.isBefore)
54 {
55 ev = Evt.beforedelete;
56 }
57 else if(Trigger.isDelete && Trigger.isAfter)
58 {
59 ev = Evt.afterdelete;
60 }
61 else if(Trigger.isundelete)
62 {
63 ev = Evt.afterundelete;
64 }
65 List<Handler> handlers = eventHandlerMapping.get(ev.name());
66 if (handlers != null && !handlers.isEmpty())
67 {
68 for (Handler h : handlers)
69 {
70 h.handle();
71 }
72 }
73 }
74 }
二.相关的实现Handler接口的类
此处例举两个类,分别实现Triggers.Handler并且实现相关的Handle方法
1.F1Handler
1 public without sharing class F1Handler implements Triggers.Handler {
2 public void Handle(){
3 List<Company_Info__c> companyInfoList = trigger.new;
4 //TODO
5 //do something start
6 system.debug('===============executeF1Handler');
7 //do something end
8 }
9 }
2.F2Handler
1 public with sharing class F2Handler implements Triggers.Handler {
2 public void Handle(){
3 List<Company_Info__c> companyInfoList = trigger.new;
4 //TODO
5 //do something start
6 system.debug('===============executeF2Handler');
7 //do something end
8 }
9 }
三.相关Trigger中Handler是否执行的Helper类
有的时候业务需要不同地方的入口进行相同的操作,需要执行不同的trigger业务模块,比如在controller正常的更新需要全部执行trigger方法模块,在其他trigger中更新此sObject则只需要一部分模块,这个时候需要相关Helper类方法来控制是否执行哪块逻辑。
1 public without sharing class TriggerExecutionHelper {
2 public static Boolean enableExecuteF1 {
3 get{
4 if(enableExecuteF1 == null) {
5 enableExecuteF1 = true;
6 }
7 return enableExecuteF1;
8 }
9 set;
10 }
11
12 public static Boolean enableExecuteF2{
13 get{
14 if(enableExecuteF2 == null) {
15 enableExecuteF2 = true;
16 }
17 return enableExecuteF2;
18 }
19 set;
20 }
21
22 }
四.Trigger代码部分
trigger代码部分用来判断是否需要执行哪些情况trigger
1 trigger CompanyInfoTrigger on Company_Info__c (after delete, after insert, after undelete, after update, before delete, before insert, before update) {
2
3 Triggers companyInfoTrigger = new Triggers();
4 if(TriggerExecutionHelper.enableExecuteF1) {
5 companyInfoTrigger.bind(Triggers.Evt.BeforeInsert, new F1Handler());
6 }
7
8 if(TriggerExecutionHelper.enableExecuteF2) {
9 companyInfoTrigger.bind(Triggers.Evt.BeforeInsert, new F2Handler());
10 }
11
12 companyInfoTrigger.Execute();
13
14 }
效果展示:
1.通过系统页面插入一条数据,默认走全部的trigger内容
相关log可以查看执行结果
2.通过匿名块执行insert则只执行trigger中一个业务模块代码
总结:如果业务逻辑特别清晰并且可以分模块处理,则可以使用此种方法,达到的效果为业务清晰明了,后期人员也便于维护。缺点为如果相关模块的Handler都对一个字段进行处理,则会有相关先后处理的问题以及出bug调试时间增多等,具体使用哪种还是看具体的业务以及个人使用习惯,业务简单直接写在trigger中也未尝不可。篇中有问题地方欢迎指出,有不懂的欢迎留言。