跟JBPM学设计模式之适配器模式
模式简介
适配器模式(Adapter),将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
说起适配器模式,大家一定会想起我们笔记本使用的适配器。插座输出的电压是220v,我们的笔记本电脑是不能直接使用的,这个时候就需要一个中介,它可以输入220v的电压,然后输出笔记本电脑所需要的电压。这个例子中,我们可以将插排输出的电压,理解为其对外发布的接口;而笔记本需要的输入电压,可以理解为客户需要的接口;而适配器的工作就是将服务者提供的接口“适配”成客户需要的接口。
适配器模式由类的适配器模式和对象的适配器模式两种不同的形式。
类的适配器模式将被适配的类的接口转换成客户需要的接口,其结构如下图所示
图 1-1.类适配器模式
从图中可以看到Adaptee类并没有TargetMethod方法,然而客户端却需要这个方法,为了是客户端可以使用Adaptee类,提供了一个中介即Adapter,其把Adatee和Target类的接口衔接起来。由于Adapter继承了Adaptee类,这就决定这个是类适配器模式。
该模式涉及到三种角色:
目标角色:其实客户需要的接口,在类适配器模式中,不可以是类。
源角色:提供服务并需要进行适配接口的类。
适配器角色:其将源接口转换成目标接口,显然其不可能是接口,而必须是一个类。
对象适配器模式,与类的适配器模式一样,其也把被适配类的接口转换成客户需要的接口,但其不是通过继承Adaptee实现的,而是通过关联Adaptee类实现的。对象适配器模式的结构如下图
图 1-2.对象适配器模式
同样从图中可以看到,Adaptee类是没有TargetMethod方法的,但是客户端是需要这个方法的。为了使客户端可以使用这个类,则需要提供一个包装类Adapter,其包装了一个Adaptee的实例,从而使其可以把Adaptee的接口与Target类的接口衔接起来。Adapter与Adaptee是关联关系,这决定了该模式是对象适配器模式。
同样这个模式中也涉及到三个角色,这与类适配器模式是一样的,不再赘述。
JBPM中的适配器模式
适配器模式分为类适配器模式和对象适配器模式,那我们也分别来看jbpm中的实现。
JBPM中的查询相关的功能使用了类适配器模式,例如历史任务查询,具体的结构如下图所示
图 1-3 JBPM中的类适配器模式
该模式涉及到的三种角色如下
目标角色:HistoryQuery作为目标角色,提供了客户需要的接口,比如设置查询参数和获取查询结果的方法等。
源角色:AbstractQuery类作为源角色,其实现了整个的查询逻辑,最终为客户提供查询服务,但是这些并不是客户所需要的接口。
适配器角色:HistoryQueryImpl作为适配器角色,它将客户需要的一些方法最终传递给为AbstractQuery来实现。
JBPM中的持久化使用的是Hibernate,其中对hibernate中的Session的封装使用的是对象适配器模式。具体的结构如下图所示
图 1-4 JBPM中的对象适配器模式
该模式涉及到的角色如下
目标角色:DbSession作为目标角色,提供了JBPM中需要使用的一些借口,这些借口有的具有一定的业务逻辑,其是hibernate不可能提供的。
源角色:Session作为源角色,其提供了持久化过程中需要的一些具体的方法。
适配器角色:DbSessionImpl作为适配器角色,其也是将客户需要的一些功能传递给持有的session对象,最终由session来进行实现。
适配器模式的优势和劣势
1. 在类适配器模式中,由于适配器类是源角色的子类,所以我们可以轻松的通过重载(override)来置换源角色中的方法;一个适配器只能适配一个类,不能同时适配子类和父类。
2. 在对象适配器模式中,同一个适配器可以把源角色及其子类都适配到目标接口;相对类适配器模式,如果想置换源角色的方法相对要难一些;新增加一些方法比较容易,同时也使用与所有的源角色。