J2EE业务层模式--应用服务
问题:
需要把多个业务组件和服务之间的业务逻辑集中起来。
服务门面<例如会话门面或者POJO门面>中包括很少、甚至不包括业务逻辑,只是提供了一个简单的、粗粒度的接口而已。而对应与一组相关的业务操作,存在一些功能,相互之间具有内聚力,业务对象模式就封装了这样一些功能,并且业务他们提供了一个接口。
为了实现用例,应用系统会调度使用多个业务对象和业务服务。但是不能再业务对象内部完成这种调度多个对象和服务、实现用例操作,因为这样会增加业务对象之间的耦合,降低他们之间的内聚性。同样,也不能把这种负责“调度”的业务逻辑放在服务门面里面,因为这种业务逻辑可能会在多个门面中造成代码的重复,这也就降低了代码的可重用性和可维护性。
对于那些不使用EJB组件的J2EE应用系统,业务层组件比如业务对象和其他服务是以POJO形式出现的。虽然这些对象都是本地对象,但是也要避免直接向客户端暴露这些对象,因为这样的暴露会导致在客户端也业务层组件之间产生耦合和依赖。及时应用系统中根本不使用业务对象,还是希望在业务层中封装业务逻辑,而不是把这种逻辑放在门面或者客户端中。
约束:
--需要尽量减少服务门面中的业务逻辑
--需要让某种业务逻辑调度多个业务对象或者业务服务
--需要在现存的业务层组件和服务之上提供一种粗粒度的服务API
--需要在业务对象之外封装专门针对特定用例的业务逻辑。
解决方案:
使用应用服务,集中、聚合特定的功能,提供一个统一的服务层。
需要有一些业务逻辑封装业务对象和业务服务,而应用服务就集中实现了这样一种业务逻辑。采用这种做法,在业务对象之外实现业务逻辑,能够减少业务对象之间的耦合。使用应用服务能够把抽象层次更高的业务逻辑封装在一个独立的组件中,有该组件调用底层的业务对象和业务服务。
即使在应用系统中没有使用业务对象,也可以用应用服务来提供一个集中的业务逻辑实现层。这种情况之下,应用服务可以包括系统中所有需要要实现服务的过程是业务逻辑,在需要处理持久化数据的时候,还可以调用数据访问对象。
在非EJB应用系统中,如果需要减少表现层组件与业务层组件之间的耦合,应用服务就能在这两个层次之间提供一个中间协调功能。与服务门面相比,应用服务提供的接口是细粒度的,而与底层的业务对象和其他服务相比则是粗粒度的。
应用服务为服务门面提供了后台的底层架构。使用该模式,门面实现起来就更简单了,门面包含的代码就更少了,因为它可以把业务处理委派给应用服务。应用服务包含业务逻辑,而服务门面通常则不包含业务逻辑。服务门面通常不包含业务逻辑。服务门面调用包含业务逻辑的应用服务和业务对象。
比如说,考虑这样一种情形:用会话门面实现服务门面。但有些应用系统中的业务逻辑会越来越复杂,所以会话门面和它的各个方法也变得冗长肥胖。采用应用服务,让会话门面吧处理请求的工作委派给他,就可以避免这种情况。
如果把业务逻辑放在一个远程会话门面,那么也会降低逻辑的可重用性。因为。既然逻辑放在了远程会话门面中,在不同的用例之间就不便于重用这些逻辑;而且很可能这些代码的重用就是一种剪刀浆糊的做法,所以也就难于维护门面代码。因此,如果需要在多个门面之间重用业务逻辑,应用服务就是放置这些逻辑的好选择,它能够把会话门面变得更简单,更漂亮,而且也更容易维护。
应用服务也有助于处理多种不同的交互形式,在有些系统中,不同的用例与同一个业务对象之间的交互会有很大的不同,另外,系统中还有可能会有多种类型的客户端,如果对同一个业务的对象,每一种客户端或用例都要加入特殊的处理方法,那么这个业务对象的就会变得特别的复杂,因为他要处理所有可能的情况。所以,对所有请求类型都通用的处理逻辑最好就封装在业务对象里面,从而实现重用;相反,每种请求类型中特殊的处理逻辑则最好放在应用服务中。
为了处理多种类型的交互形式,可以使用后文介绍的应用服务分层的策略。该策略把不同的应用服务分成了自下而上的多个层次,最底层的服务封装了通用的业务逻辑,然后的一个层专门与特定用例相关的业务逻辑,最后,顶层的应用服务则负责与客户端相关的业务处理。
应用服务可以用来调用外部服务。如果应用系统需要访问外部服务,比如EMAIL系统、遗留系统或者web service,那么就可以在应用服务中实现这些服务的访问逻辑,这样就能提供一个可重用的服务组件。
设计手记:
在应用服务和业务对象实现业务逻辑的时候,可能会考虑业务逻辑究竟放在哪里比较合适。业务对象中也能包含业务逻辑,但是有些开发者就是忽略了这一点,不在业务对象中实现任何的业务逻辑。
他们可能会把所有的业务逻辑作为一个单独的层次,有应用服务来实现,另一个方面,也有些人会把所有的业务逻辑都实现在业务对象中,根本不加入那个服务层,这样业务对象就变得肥胖不堪,难于重用。
设计手记:
对于使用EJB组件的企业应用,会话门面利用session bean在业务层实现了门面模式。这些门面的作用,是以粗粒度的形式封装了业务功能,并把这些功能暴露给应用客户端,从而隐藏业务组件的复杂性以及业务组件之间的交互细节。但是,如果正在设计的企业应用并不包含EJB组件、仍然需要会话门面的功能。这时候实现就不是session bean,相反,我们是使用POJO门面,这样就有了POJO门面这个概念。
为了用一套通用的词汇、说法讨论POJO门面和会话门面,我们引入了“服务门面”的概念。所谓服务门面,就是一种业务层的门面,有POJO或者session bean来实现。所以,如果在书中看到了服务门面这个概念,泛指了这两个门面,这点要注意。
小结:为什么加入应用层:
1、从业务对象这个角度来说,如果把所有的业务全部放倒业务对象中,则会不适合,不自然。放入业务对象中的职责应该是本质的,非本质的业务逻辑我们应该放在应用逻辑层,比如处理不同的客户端、实现不同的用例等等
2、从服务门面这个角度来说,如果使用了应用服务这一层,对于服务门面来说比较好,因为服务门面中不应该包含逻辑,服务门面可以把工作委派给应用服务这一层。
3、从调用其他服务这个角度来说,在业务对象这一层调用其他的服务好像不是很合适,因为不是本质的业务逻辑,这个时候我们将调用其他的服务这个职责放倒应用服务岂不是更好。
4、从粗粒度这样的角度来说,应用服务比业务对象的粒度要粗,而服务门面则比应用服务的粒度要粗,所以更便于服务门面这一层的重用。