Activiti的设计模式

https://blog.csdn.net/boxiong86/article/details/78434515

Activiti提供了命令拦截器的功能,外界对Activiti流程中各个实例进行操作,实际可以看作是对数据进行相应的操作,在此过程中,Activiti使用了设计模式中的命令模式,每一个操作数据库的过程,均可被看作为一个命令,然后交由命令执行者去完成。除此之外,为了能让使用者可以对这些命令进行相应的拦截(进行个性化处理),Activiti还使用了设计模式中的责任链模式,使用者可以添加相应的拦截器(责任链模式中的处理者)。
4.1命令模式

GoF的设计模式中,命令模式属于行为型模式,它把一个请求或者操作封装到命令对象中,这些请求或者操作内容包括接收者信息,然后将该命令对象交由执行者执行,执行者不需要关心命令的接收人或者命令的具体内容,因为这些信息均被封装到命令对象中。命令模式中涉及的角色以及其作用如下:

n 命令接口(Command):声明执行操作的接口。

n 接口实现(ConcreteCommand):命令接口实现,需要保存接收者的相应操作,并执行相应的操作。

n 命令执行者(Invoker):要求命令执行此次请求。

n 命令接收人(Receiver):由命令的实现维护实例,并在命令执行时处理相应的任务。

接下来,编写一个最简单的命令模式

 

然后创建命令接收者

 

本例中命令接者只有一个实现,方法A(doSomething)打印“命令接收人执行命令A”,方法BdoSomethingB)打印“命令接收人执行命令B”,接下来创建命令执行者

 

注意命令执行者的实现中,调使用命令的execute方法,并将相应的命令接收人设置到命令的execute方法参数中。此处创建命令接收者的方式,可以使用其他的设计模式完成,例如工厂模式,单态模式等等,此处为了更加简单,直接new一个CommandReceiver的实现类。接下来,为命令接口提供两个实现CommandA和CommandB

 

CommandA的实现中,直接让命令接收执行方法AdoSomethingA),CommandB的实现与CommandA类似,只是执行命令接收者的方法BdoSomethingB)。到此,命令模式的各个角色已经创建完毕,接下来编写客户端代码,让命令执行者执行相应的命令。

 

先创建一个命令执行者,然后创建两个命令,并交由命令执行者执行,最终执行结果将输出“命令接收人执行命令A”和“命令接收人执行命令B”。

现在了解了GoF的命令模式,在Activiti中,每一个数据库的CRUD操作,均为一个命令的实现,然后交给Activiti的命令执行者执行。Activiti使用了一个CommandContext类作为命令接收者,该对象维护一系列的Manager对象,这些Manager对象就像J2EE中的DAO对象。除了命令接收者外,Activiti还使用一系列的CommandInterceptor(命令拦截器),这些命令拦截器扮演命令模式中的命令执行者角色。那么这些命令拦截器是如何工作的呢?接下来需要了解责任链模式。

4.2责任与命令模式一样,

任链模式也是GoF的设计模式之一,同样也是行为型模式。该设计模式为了让多个对象都有机会处理请求,从而避免了请求发送者和请求接收者之间的耦合。这些请求接收者将组成一条,并沿着这条链传递该请求,直到有一个对象处理这个请求为止,这就形成一条责任链。责任链模式有以下参与者:

请求处理者接口(Handler):定义一个处理请求的接口,可以实现后继链。

请求处理者实现(ConcreteHandler):请求处理接口的实现,如果它可以处理请求,就处理,否则就将该请转发给它的后继者。链模式

 

定义了一个请求处理者的抽象类,并且定义了请求的处理方法,需要由子类实现,需要注意的是,处理请求方法(execute)的参数为一个Request对象,本例中的Request对象只是一个普通的类,若责任链模式结合命令模式一起使用的话,那么execute方法的参数可以是命令模式中的命令接口。除此之外,Handler还定义了一个next属性,在这里表示下一任处理者的对象,此处提供setter方法,由客户端决定下一任请求处理者是谁。

 

Request对象只有一个doSomething方法,如果将Request设置为一个接口的话,那么它也可以像命令模式的命令接口一样(见命令模式的Command)有多个实现。

 

HandlerA继承了Handler并且实现了execute方法,当该处理器处理完自己的事情后,再将请求交由下一任处理者继续执行请求。在责任链中,可以新建多个这样的请求处理者

除了若干个请求处理者的实现外,还需要新建一个真实的请求处理者,实际上就算再多这样的请求处理者实现,依然没有对请求作任何处理,只是交由下一任处理者执行,因此需要一个真实的请求处理者来终结这条责任链。

 

最终的请求处理者最终执行了请求,并且不再往下执行(不使用next属性)。下面编写客户端代码,使用这个责任链。

 

定义了一个请求处理者的集合,然后按照该集合顺序通过setNext方法为每一个请求处理者设置下一任的请求处理者,setNext方法最后返回第一任处理者(HandlerA)。需要注意的是,由于定义了最终的请求处理者为ActualHandler,因此需要将其放到集合的最后,作为终止整个责任链的角色。最终运行顺序为:“请求处理者A处理请求”,“请求处理者B处理请求”,“执行请求”。

4.3编写自定义拦截器

前面讲解了命令模式与责任链模式,Activiti的拦截器,就是结合这两种设计模式,达到拦截器的效果,每次Activiti进行业务操作,都会封装为一个Command放到责任链中执行。知道其原理后,可以在实现自定义配置类时,编写自己的拦截器。首先编写第一个拦截器实现

 

InterceptorA实现CommandInterceptor接口,实现责任链模式时,在拦截器的execute方法中,执行完拦截器自己的程序后(输出业务命令),会执行责任链的下一个拦截器的execute方法。了解责任链模式后,不难发现,此处的next就是拦截器中的下一任请求处理者,而此处的请求,则是命令模式中的Command接口,编写的InterceptorA就是责任链模式中请求处理者的其中一个实现。

使用同样的方式,创建拦截器B,与拦截器A类似,输出字符串与业务命令,再将请求(此处为Command)交由下一执行者执行。完成了两个拦截器后,再去实现父类的初始化拦截器方法,将我们的拦截器“侵入”到Activiti的责任链中,

 

initCommandInterceptors方法,用于初始化命令拦截器集合。我们的自定义集合,加上Activiti的默认集合,形成拥有多个拦截器集合,也就是一条责任链。Activiti的默认集合,会加入日志拦截器、createTransactionInterceptor方法返回的拦截器、包含业务操作的命令、事务拦截器。

 

部署了一个简单的流程,此时运行该测试程序,可以看到拦截器打印的效果:

 

可以看到,每执行一个命令,都会经过我们定义的拦截器A和B

项目中编写了节点跳转命令

原文地址:https://www.cnblogs.com/yuluoxingkong/p/14247037.html