public class BookingFacade
{
public void ProcessBooking(CustomerDetails customer,BookingDetails booking)
{
if(IsValidate(customer))
{
//通过一个连接辅助类提供数据库连接对象
DBHelper helper = new DBHelper();
Object conn = helper.GetConnection();
CustomerOperation cOper = new CustomerOperation(conn);
BookingOperation bOper = new BookingOperation(conn);
If(!cOper.Contains(customer))
{
cOper.AddCustomer(customer);
}
bOper.AddBookong(booking);
//确保连接对象被释放
helper.ReleaseConnection(conn);
}
}
}
Façade由于处于包装的顶层,很容易替换内部的数据操作形式而不必改变客户端代码,为了提高系统的可扩展性和灵活性我们总是期望这样一种理想的状态。但是,实际情况往往不尽人意,客户端总是或多或少的绑定某些特定的数据表示,比如如果客户对象的信息发生更新,那么服务端和客户端的CustomerDetails类的版本甚至相应数据库表都要更新,同时客户端界面上也要发生一些改动以反映出这种更新。此时,衡量我们设计好坏的标准就变成刚才提到在客户端特定数据绑定的多少问题以及改动程度的轻重问题。
更深入一步,到此为止我们只是提到在服务端使用Façade,但并没有说明这个Façade包装的是一个Web服务还是一个Remoting,事实上这无关紧要。因为无论是哪种形式,客户端要调用的仍旧是这个Façade对象公开的方法,从而屏蔽了对其封装了的那些底层对象方法的调用,也就是隔离了底层的差别。讲到这里,不能不提一下SOA(面向服务的架构),很多人误认为系统中使用了传统的Web服务或者Remoting就符合SOA了,实际上是错误的,或者说是不确切的。因为至少有一个事实可以证明这一点,那就是SOA对外部提供的服务是有粒度要求的(应该是粗粒度的),难道仅仅对外提供了一个登录服务就能称其为SOA架构吗,这显然不是SOA的初衷。从某种角度而言,传统的Web服务和Remoting提供的服务仅仅是SOA提供服务的构成元素,也就是说我们能够将前者转变为SOA中所谓的服务,实际上这里提到的Façade正是这一转变的关键所在。
最后,再来讨论一下Façade和事务处理。也许很多人因为要使用合适的分布式事务处理煞费苦心,也因为MSDTC的种种问题而气急败坏,但是如果将各种数据库相关的操作集中在一起在服务器端使用数据库本身的事务机制则是非常有效且简便的解决方法,Façade正好成全了这样的构想。
我们可以用多种方式给Façade增加事务支持,一种方式就是在刚才的数据库连接辅助类中增加一个方法:GetTransaction()返回一个事务对象,它将控制Façade操作的全过程。代码如下:
public class BookingFacade
{
public void ProcessBooking(CustomerDetails customer,BookingDetails booking)
{
if(IsValidate(customer))
{
DBHelper helper = new DBHelper();
Object conn = helper.GetConnection();
Object transaction = conn.GetTransaction();
//开始事务
transaction.Begin();
try
{
CustomerOperation cOper = new CustomerOperation(conn);
BookingOperation bOper = new BookingOperation(conn);
If(!cOper.Contains(customer))
{
cOper.AddCustomer(customer);
}
bOper.AddBookong(booking);
}
catch(Exception ex)
{
//TODO这里应捕获特定异常
transaction.Rollback(); //事务回滚
}
finally
{
//提交事务
transaction.Commit();
//关闭连接
helper.ReleaseConnection(conn);
}
}
}
}
另外一个方法就是使用COM+的事务处理,由于它使用了两阶段的处理过程,因此开销大一些。需要指出的是,当在Web服务中实现Façade的事务控制是非常简单容易的,因为此时可以使用<WebMethod>特性中(Attribute)的Transaction属性。事务处理将自动进行,除非有异常引发。示意代码如下:
public class BookingFacade
{
<WebMethod(false,TransactionOption=TransactionOption.RequiresNew)>
public void ProcessBooking(CustomerDetails customer,BookingDetails book)
{
......
}
}