商业逻辑和客户端/表示层一起编码,一个清楚的角色
区分是不可能的。商业逻辑和表示逻辑程序员将踩着
各自的脚尖,如果同样在表示层
编程。
我们的讨论的结论(takeaway point)是我们需要一个
服务器端的抽象作为entity bean的中介和缓冲。
session bean正是为这个
设计的。
因此:
用一个叫做session facade的session bean层来
封装entity bean层。客户端应该只能存取session
bean,不能存取entity bean。
session facade模式把传统的facade模式的好处
应用到
EJB,通过完全对客户端隐藏服务器上的
对象模型,通过用session bean层作为客户端
的单独存取点。图1.2描绘了架构通过这个方法
能被改进。session facade模式还通过在一个
网络调用的增强的用例的执行和提供一个干净
的层来封装完成这个用例的商业和工作流逻辑
带来好处。session facade通常作为无状态
session bean来实现。(虽然这个模式可以用
有状态session bean来实现。)
为了描绘这个paradigm怎样工作和这个paradigm
带来的好处,让我们用我们先前的例子。我们用
来的传输存款的用例的商业逻辑现在将在一个
session bean中替代,这个session bean有一个
叫做TransferFunds(userpk,accountpk,accountpk
,amount)的方法。那个Bank Teller session bean
因此完成大批(bulk)对Users和Bank账户的操作,
如图1.3所示。
因为Bank Teller session bean和User和Account
entity bean共存,它应该被hard-coded来和entity
bean通过local interface通信,因此把需要执行
那个用例的网络开销减小到一个调用(从客户端
到Bank Teller的调用)。同样,所有对entity bean
层的更新应该在Bank Teller所发起的事务中完成,
在它的deployment discriptor中定义,几乎总是,
用TX_REQUIRED的设置。这样有效的用一个事物
包装了整个用例,确保所有对entity bean的更新都在
Bank Teller的transferfunds方法所发起的事务中
完成。
session facade模式是今天使用中的最基础的
EJB模式(这就是为什么它是这本书的第一个
模式)。它不但提供性能好处,也建议了为
EJB 系统分配(systems-partitioning)你的
J2EE应用的标准架构,客户端和服务器被一个
session bean层所分离,这个session bean
的方法映射到(并且包括商业逻辑)所有的应用
中的用例。
进一步用Bank Teller例子,在bank应用中明显
有比传输存款更多的用例。使用session facade
模式,session bean将被创建来分组用例,使
相似的函数在一个bean中。因此我们可以增加其
它辅助(ancillary)银行操作到Bank Teller(如
withdrawFunds,depositFunds,getBalance())。
另外在banking应用中,为了不同目的的用例
也可以分组到一个session bean。例如,每个
银行有一个存款部门(loans department)。
需要去建模存款部门的操作的用例和Bank Teller
的用例没有关系。;所以,它们将分组成一个
LoanService session bean。相似的,一个
banking应用将也需要一个session bean来封装
和投资(investment)相关的用例。使用session
facade模式,这个baking应用的架构铺设(
architectural layout)将会如图1.4。
session facade模式工作得如此之好,以至于
常常它很容易被滥用。很通常能发现session
facade被误用的项目:
1.创建一个session bean巨类(God-class)。
常常开发者把系统中所有的用例都放在一个
session bean中。这导致臃肿的session
bean并降低开发生产力,因为所有的开发者
都需要用这一个类。session bean应该被分成
相关的用例的组群(house groupings)。
2.把领域(domain)逻辑放在session bean中。
一个设计得好的OO领域模型应该包括所有的
你的应用中的商业/用例逻辑(Fowler,2001)。
大多数session facade方法应该只是代理(
delegate)合适的entity bean,除非用例
包含需要跨不同bean而且不是直接有联系的
工作流(workflow)逻辑。