信息工程是以當前數據系統為基礎,在一個(gè)企業(yè)或企業(yè)的主要部門(mén),關(guān)于建設信息系統的規 劃、分析、設計和構成的一整套相互關(guān)聯(lián)的正規化、自動(dòng)化的技術(shù)應用。 --- James Martin
正如上面信息工程的創(chuàng )始人James Martin為信息工程的概念所做定義類(lèi)似,模式(Patterns)的創(chuàng )始人建筑師Christopher Alexander在<模式語(yǔ)言,1977、1979>一書(shū)中對模式的概念進(jìn)行了如下描述(附注:書(shū)名后面的年份代表在各個(gè)不同時(shí)期的作品,下面形式同上):每一個(gè)模式描述了一個(gè)在我們周?chē)粩嘀貜桶l(fā)生的問(wèn)題,以及該問(wèn)題的解決方案的核心。這樣,你就能一次又一次的使用該解決方案而不必做重復勞動(dòng)。每個(gè)模式是由三部分組成的一個(gè)規則,這個(gè)規則描述特定環(huán)境、問(wèn)題和解決方案之間的關(guān)系。簡(jiǎn)單的說(shuō),沒(méi)有一個(gè)模式是獨立的實(shí)體,每個(gè)模式都存在著(zhù)相互支持,但支持的程度不同:大的模式可以?xún)惹缎〉哪J?,同等層次的模式并列存在,而小的模式被嵌入到大的模式之中?: --- Christopher Alexander
模式的概念在軟件行業(yè)被采用以后,得到的廣泛的發(fā)展,現在已經(jīng)存在許多種類(lèi)型的模式應用,其中比較有名的箸作有:GoF(Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四人,簡(jiǎn)稱(chēng):Gang of Four[GoF])的<設計模式,1995>,Martin Fowler的<分析模式,1997>,Frank Buschmann等人的<體系結構模式,1996、2000>、Jim O.Coplien、Niel Harrison等人的<編程模式,1995、1996、1998、1999>和Deepak Alur等人的<J2EE核心模式,2001>等,其中最具影響的是GoF的<設計模式>一書(shū),書(shū)中詳細討論了三種類(lèi)型,共23種模式。好的設計源于工作中經(jīng)驗的積累,當設計使用標準的模板以模式的方式進(jìn)行交流時(shí),模式就成了交流和重用的強大機制,并且可以改善設計和開(kāi)發(fā)軟件的方式。模式可以幫助我們在一個(gè)特定的環(huán)境里整理并記錄已知的可重現的問(wèn)題及解決方案,并且通過(guò)模式來(lái)與他人交流這些知識,這些模式可以解決在不同環(huán)境中重復出現的問(wèn)題。模式可以使設計重復使用,重復使用已知的解決方案可以縮短設計和開(kāi)發(fā)應用的周期,有效的使用模式,可以使我們遠離重復投資的怪圈。模式的關(guān)鍵在于簡(jiǎn)單性和可重現性。
舉一個(gè)模式應用的簡(jiǎn)單示例。例如,在你的便攜式電腦上運行一個(gè)進(jìn)程中的對象,并且這些對象需要和運行在另一進(jìn)程中的別的對象通信,也許這一進(jìn)程并不在你的便攜式電腦上,而在別的地方。你又不想讓系統中的對象擔心如何找尋網(wǎng)上的其他對象或者執行遠程過(guò)程調用。這時(shí),可以使用代理(Proxy模式,詳見(jiàn)GoF的<設計模式>一書(shū))模式來(lái)解決這個(gè)問(wèn)題,你能做的事就是為這個(gè)遠程對象在你的本地過(guò)程中建立一個(gè)代理對象,該代理對象和遠程對象具有相同的接口。你的本地對象利用通常處理過(guò)程中的消息發(fā)送來(lái)和代理交談。這時(shí)代理對象負責把消息傳送給實(shí)在對象,而不管實(shí)在對象位于何處。
由于下面要講的Java 2平臺的企業(yè)版(J2EE)應用模式中很多用到了設計模式與重構(Refactoring)的概念,所以在此有必要再概要介紹一下重構的概念。重構已經(jīng)被證明可以阻止軟件的腐朽和衰敗,關(guān)于重構方面的有名箸作當然首推是Martin Fowler所寫(xiě)的<重構,1999>一書(shū)了,書(shū)中詳細介紹了重構的七大類(lèi)型,共70余種具體的重構手法,同時(shí)也指出測試機制在重構中的重要性。書(shū)中Martin Fowler對重構的概念進(jìn)行了詳細說(shuō)明:
重構是對軟件內部結構的一種調整,目地是在不改變[軟件之可察行為]的前提下,提高其可理解性,降低其修改成本。重構是一種有紀律的、經(jīng)過(guò)訓練的、有條不紊的程序整理方法,可以將整理過(guò)程中不小心引入的錯誤的機率降到最低,本質(zhì)上說(shuō),重構就是在代碼寫(xiě)好之后改進(jìn)它的設計。重構之前,首先檢查自己是否有一套可靠的測試機制,這些測試必須有我檢驗能力。
--- Martin Fowler
建立于Java編程語(yǔ)言和Java技術(shù)基礎之上的J2EE平臺是最適用于企業(yè)級分布式環(huán)境的應用結構,它被設計為面向多層體系的結構。J2EE包含下面關(guān)鍵技術(shù):Java服務(wù)器頁(yè)面(Java Service Page,JSP)、Servlet、Enterprise JavaBeans(EJB)組件、Java消息服務(wù)(Java Message Service,JMS)、JDBC和Java命名與目錄接口(Java Naming and Directory Interface,JNDI)。由于J2EE平臺是分層系統,所以我們將J2EE的層次模型化,這個(gè)模型使得我們將職責邏輯地分到不同的層中,共分了五個(gè)層次:客戶(hù)層、表示層、業(yè)務(wù)層、集成層和資源層。因為客戶(hù)層和資源層并不是J2EE平臺直接關(guān)注的問(wèn)題,所以后面介紹的15個(gè)J2EE應用模式全部屬于上面五層中的中間三層,其中表示層模式包含與Servlet和JSP技術(shù)相關(guān)的模式、業(yè)務(wù)層模式包含與EJB技術(shù)有關(guān)的模式、集成層模式包含與JMS和JDBC有關(guān)的模式。具體模式可參看下面表格:
表一:表示層模式 模式名 簡(jiǎn)單描述
截取過(guò)濾器(Intercepting Filter) 促進(jìn)請求的預先處理和后處理
前端控制器(Front Controller) 提供請求處理的集中控制器
視圖助手(View Helper) 把與表示層格式化無(wú)關(guān)的邏輯封裝到助手組件
復合視圖(Composite View) 從原子的子組件創(chuàng )建一個(gè)聚集視圖
工作者服務(wù)(Service To Worker) 合并分發(fā)者組件、前端控制器和視圖助手模式
分發(fā)者視圖(Dispatcher View) 合并分發(fā)者組件、前端控制器和視圖助手模式,把許多動(dòng)作推遲到視圖處理
表二:業(yè)務(wù)層模式
模式名 簡(jiǎn)單描述
業(yè)務(wù)委托(Business Delegate) 把表示層和服務(wù)層分隔開(kāi),并且提供服務(wù)的外觀(guān)和代理接口
值對象(Value Object) 通過(guò)減少網(wǎng)絡(luò )對話(huà),以加速層之間的數據交換
會(huì )話(huà)外觀(guān)(Session Facade) 隱藏業(yè)務(wù)對象復性,集中化工作流處理
復合實(shí)體(Composite Entity) 通過(guò)把參數相關(guān)的對象分組進(jìn)單個(gè)實(shí)體bean,表示設計粗粒度實(shí)體bean的最好經(jīng)驗
值對象組裝器(Value Object Assembler) 把來(lái)自多個(gè)數據源的值對象組裝成一個(gè)復合值對象
值列表處理器(Value List Handler) 管理查詢(xún)執行、結果緩沖、以及結果處理
服務(wù)定位器(Service Locator) 封裝業(yè)務(wù)服務(wù)查找和創(chuàng )建的復雜性,定位業(yè)務(wù)服務(wù)工廠(chǎng)
表三:集成層模式
模式名 簡(jiǎn)單描述
數據訪(fǎng)問(wèn)對象(Data Access Object) 抽象數據源,提供對數據的透明訪(fǎng)問(wèn)
服務(wù)激發(fā)器(Service Activator) 加速EJB組件的異步處理
由于J2EE模式眾多,篇幅有限,這里只概要介紹其中的一種應用模式 - 集成層的數據訪(fǎng)問(wèn)對象(DAO)模式,有興趣的讀者可以參看下面參考文獻中的資料。
數據訪(fǎng)問(wèn)對象模式
數據訪(fǎng)問(wèn)對象模式
1、問(wèn)題
根據數據源不同,數據訪(fǎng)問(wèn)也不同。根據存儲的類(lèi)型(關(guān)系數據庫、面向對象數據庫等)和供應商不同,持久性存儲(比如數據庫)的訪(fǎng)問(wèn)差別也很大。當業(yè)務(wù)組件(如會(huì )話(huà)bean)或表示組件(如助手組件)需要訪(fǎng)問(wèn)某數據源時(shí),它們可以使用合適的API來(lái)獲得連接性,以及操作該數據源。但是在這些組件中包含連接性和數據訪(fǎng)問(wèn)代碼會(huì )引入這些組件及數據源實(shí)現之間的緊密耦合。組件中這類(lèi)代碼依賴(lài)性使應用程序從某種數據源遷移到其它種類(lèi)的數據源將變得非常麻煩和困難,當數據源變化時(shí),組件也需要改變,以便于能夠處理新類(lèi)型的數據源。
2、解決方案
使用數據訪(fǎng)問(wèn)對象(DAO)來(lái)抽象和封裝所有對數據源的訪(fǎng)問(wèn)。DAO管理著(zhù)與數據源的連接以便于檢索和存儲數據,DAO實(shí)現了用來(lái)操作數據源的訪(fǎng)問(wèn)機制。依賴(lài)于DAO的業(yè)務(wù)組件為其客戶(hù)端使用DAO提供了更簡(jiǎn)單的接口,DAO完全向客戶(hù)端隱藏了數據源實(shí)現細節。由于當低層數據源實(shí)現變化時(shí),DAO向客戶(hù)端提供的接口不會(huì )變化,所以該模式允許DAO調整到不同的存儲模式,而不會(huì )影響其客戶(hù)端或業(yè)務(wù)組件。重要的是,DAO充當組件和數據源之間的適配器。
3、實(shí)現策略
通過(guò)調整抽象工廠(chǎng)(Abstract Factory)模式和工廠(chǎng)方法(Factory Method,這二個(gè)創(chuàng )建型模式的實(shí)現詳情可參看GoF的<設計模式>一書(shū))模式,DAO模式可以達到很高的靈活度。 當低層存儲不會(huì )隨著(zhù)實(shí)現變化而變化時(shí),可以使用工廠(chǎng)方法模式來(lái)實(shí)現該策略,以產(chǎn)生應用程序需要的大量DAO,如下面類(lèi)圖1所示。 當低層存儲隨著(zhù)實(shí)現的變化而變化時(shí),策略可以通過(guò)使用抽象工廠(chǎng)模式而實(shí)現。抽象工廠(chǎng)可以基于工廠(chǎng)方法實(shí)現而創(chuàng )建,并可使用工廠(chǎng)方法實(shí)現,該策略提供一個(gè)DAO的抽象工廠(chǎng)對象,其中該對象可以構造多種類(lèi)型的具體的DAO工廠(chǎng),每個(gè)工廠(chǎng)支持一種不同類(lèi)型的持久性存儲實(shí)現。一旦你獲取某特定實(shí)現的具體DAO工廠(chǎng),你可以使用它來(lái)生成該實(shí)現中所支持和實(shí)現的DAO,如下面類(lèi)圖2所示。
4、應用
當數據訪(fǎng)問(wèn)代碼被直接嵌入到有其他不相關(guān)職責的某類(lèi)中時(shí),就會(huì )使修改變的十分困難。這時(shí)可以采用分離數據訪(fǎng)問(wèn)代碼的解決方案,將數據訪(fǎng)問(wèn)代碼抽取到一個(gè)新類(lèi)中,并且把該新類(lèi)邏輯或者物理地移動(dòng)到離數據源比較近的位置,這樣可以增強模塊性和可重用性,如下面圖3所示。具體作法可以使用提煉類(lèi)(Extract Class,一種重構手法,細節可參看Martin的<重構>一書(shū))方法創(chuàng )建一個(gè)新類(lèi),并將原來(lái)類(lèi)中把數據訪(fǎng)問(wèn)代碼移動(dòng)到這個(gè)新的數據訪(fǎng)問(wèn)對象(DAO)類(lèi),使用這個(gè)新的DAO對象從控制器類(lèi)中訪(fǎng)問(wèn)數據。
示例:持久性邏輯被嵌入到一個(gè)使用新DAO對象管理的持久性的某企業(yè)新DAO對象中,把持久性代碼和該企業(yè)新DAO對象代碼結合起來(lái)會(huì )創(chuàng )建脆弱的、緊密耦合的代碼。當持久性代碼是該企業(yè)新DAO對象的一部分時(shí),對該持久性存儲的任何改動(dòng)都要求更改該新DAO對象的持久性代碼。這種耦合對企業(yè)新DAO對象代碼維護會(huì )帶來(lái)負面的影響。下面圖4為運用分離數據訪(fǎng)問(wèn)對象方法對其進(jìn)行重構改進(jìn)后的結果。
在15個(gè)J2EE模式中,每個(gè)模式都作用于設計模式和構架模式之間的某些方面。每個(gè)模式不是孤立存在的,需要其它模式的支持才能更加體現其含義和用處,為了最大限度的用好模式,還需要充分理解模式之間的關(guān)系。