(大量參考PoEAA...-_-...)
最近網上看到這樣的帖子<<誰能告訴我Hibernate有何優秀之處>> 作者給出了對hibernate在實現orm的諸多不滿和懷疑。而且很多開發人員都有著這樣疑問,“怎么這個流行東東,我用起來就是不順手呢?”,“或許這個東東只是用來吹牛的…”。然而,這或許很可能是因為,你習慣的架構模式開發策略并不適合使用orm這種持久化模式。用了反而是加大復雜度降低性能和效率。比如,用慣了resultset,喜歡把resultset放在表示層作為展示的數據結構的人。這樣的開發人員因為習慣了二維表為核心進行開發,對于Hibernate這樣的orm工具根本就沒辦法了解其優勢了。但是這并不是說這種以二維表的架構模式就比較差了,只是不同的模式有不同的優缺點就看所在的應用是否適合使用了。或許你就一直在使用這樣的模式在開發應用,自己還沒有意識到(甚至一直以為這樣的方式可以適應任何應用,:-)。反而被其他架構模式中才會用到的框架搞的暈頭轉向甚至被誤導。事實上,像前面提到的以二維表為核心的架構被稱之為”表模塊”架構(設計)模式。
何為“表模塊”(table module)?“處理某一個數據庫表、視圖或虛擬表中所有行為的業務邏輯組成的一個實例”。最初,我就是從馬丁同學的POEAA中得到的這個定義。在書中他被定義在DomainLogic 層次或者該層次的一部分,DomainLogic也就是其他架構模型中的BizLogic層。與該模式相對應個還有完成相似功能的DomainModel以及TransactionScript模式。該層次的職責是專門處理業務邏輯。
簡單的講,所謂“表模塊”就是以一個類對應數據庫中一個表(視圖)的數據來組織業務邏輯。從設計層次表妙面上看這種結構很像經典OO模型,同樣是以不同對象對應不同邏輯。但是,它與領域建模不同之處在于,它的對象并不表示一個問題領域對象在軟件系統中的映射。而是表示對一組數據的處理邏輯,而通常這組數據的結構是重數據庫表或試圖上的二維數據結構。當然也可以來自其他集成部分,比如返回兩位數據結構的webservice。
這里給出個比較形象的例子:

(上圖)感覺像比較標準的OO吧,好象一個Contract的對象表示合同,而Product表示產品,還有他們之間的關聯關系。但是其實現實給出幾個方法的時候就看出區別了。Product內部的數據其實就是一個兩位結構的rowset。而不像真正的領域模型分析出來的表示一個Product的數據,Contract也是如此。

你會發現tableModule的類中一個對象其實對應一個表的數據,其擁有的操作也有很多是多數據記錄的。多數據記錄的操作在真正的領域中往往應該放在類似Manager這樣的實體中,而不是業務實體本身。
使用這種模式實現的業務邏輯層不像領域模型模式可以適應搞復雜度的邏輯。但是由于它更親近于數據持久的二維表,沒有像領域模型那樣需要復雜的ORM支持。書對于數據驅動的應用或模塊非常適合。POEAA中也已經給出了這種bizLogic最有效的持久層實現,就是table getway,當然也可以使用其他的方式比如“查詢工廠”。
事實上,最多使用這種模式的情況是當后臺數據源大部分都是一種兩維甚至多維數據結構的時候進行。比如一個極端的例子(幾乎沒有業務),一個應用的復雜查詢模塊,這種模塊就是一個查詢模型加上一組對數據進行排列統計過濾的TableModule。
表模塊還具有很多特點:處理的二維數據表將成為代碼的核心部分。所以,是否使用tableModule還會取決于整個應用的其他部分是否對這種二維表提供強大的支持。(如上圖)
優點:持久層架構簡單,在復雜度大的以數據為核心的應用中開發效率極高。而且表模塊能夠識別的table越多,能夠處理table的組建工具越強,這種模型的能力越強。
缺點:不能適應復雜的應用邏輯,或者與表結構差別較大的應用邏輯。由于沒有對內部的兩位數據表(table)進行有效標識的方式(比如,無法快速簡單的確定使用table是否是需要的數據內容),對于大量細顆粒的邏輯會增加其復雜度。
其實java中的 rowset/jdbc resultset,.net中的
dateSet/dataTable都屬于表模塊操作的二維表。但是,由于.net在GUI層面以及持久化層面對他自己的”二維表”的強大支持使得 TableModule幾乎成為MS.Net上的首選模式。這也就可以解釋了,許多.net開發人員一直抱怨,看到dataset/dataTable泛濫,甚至在WebService中也是這樣。而java中卻有所不同,雖然有持久化用到的jdbc/resultSet的支持(事實上jdbc/ado 給出的接口都只直接適合TableModule。),然而其他方面就少得可憐了。所以,使用java還是以其他的bizLogic架構模式為好。除非你的邏輯真的很簡單,簡單到把resultSet放在jsp中都不會造成邏輯混亂。又或者你能夠自己提供一套完整的 rowset組建框架。