构建高效的企业级Java应用系列(一)架构篇——2

2:跨越组件边界优先采用松耦合
      首先需要明确三个概念:紧耦合、延迟绑定、松耦合。
      紧耦合:如果一个给定的“事物”必须做出变化,以适应另一个“事物”的变化,我们称前者紧耦合于后者。例如:ServletAPI紧耦合于HTTP协议规范:如果HTTP改变其规则,则ServletAPI(至少是javax.servlet.http包)也需要做出相应的修改。
       延迟绑定:先看下面的一段代码

      Class c = Person.class;
      Object o 
= c.newInstance();
      Method m 
= c.getMethod("getAge"new Class[ ] { });
      
int age = ((Integer)(m.invoke(o, new Object[ ]  { })).getIntValue();

      我们常常认为上面的代码是松耦合代码,因为Person类及其getAge方法没有直接出现在代码中。这样,如果Person类的getAge方法发生了变化,编译器也不会报错。然而,尽管我们在语法上没有绑定于Person类,但实际存在语义上的绑定。如果这个无参数的getAge方法并不存在,或者通过c引用的Class对象不可访问,这段代码还是要失败,而且是直到运行时才会被发现。所以,这并不是松耦合代码,而是松绑定代码。
      Java动态方法调用机制有时也被称为延迟绑定,直到运行时刻,也就是当确切知道具体对象的时刻,才能决定调用的是继承体系中的哪个方法。
      松耦合:当改变组件的实现(甚至于从Java移植至.NET)不会影响到组件使用者;或者组件使用者的改变的问题不需要组件做出相应的改变。

      其实在构建组件时,我们需要考虑的不仅仅是如何实现松耦合,这样只会让我们陷入为了实现而实现的泥潭当中。在构建边界之内的紧耦合其实是必不可少的。只要我们遵循有接口定义的契约,组件调用者就能和组件的实现保持松耦合关系。
      对于企业系统而言,由于其复杂的本质,确实是需要松耦合。企业系统需要访问其他系统,也会被其他系统访问,包括公司内部或外部的系统。这里需要针对不同环境下的组件加以区分:
      对于远程组件,要避免紧耦合的一种比较可行的方法是:优先采用数据驱动的接口,而不是行为驱动的接口(本质上就是传递消息和RPC的区别)。虽然,这么做可能会破坏组件的面向对象的性质,但是这未必是件坏事(在后续建议中讨论)。对通讯保持上下文完整(content-complete)也对促进远程组件的松耦合有帮助。
      对于本地组件,本地方法调用的成本要远远低于远程方法调用的成本,所以是否采用“数据驱动”或“上下文完整”就不再重要。例如,根据Servlet规范,在Web应用和容器之间能安全地创建Context对象,作为Web应用和容器之间保持一定距离的方式;例如,如果我们能向Context请求有关组件的文件资源(getResource和getResourceAsStream),就不需要知道容器的部署模型如何去执行的。

posted on 2007-04-14 19:34 万博 阅读(295) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2007年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

导航

统计

留言簿(1)

随笔档案(13)

搜索

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜