




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
PetShop的系統(tǒng)架構(gòu)設(shè)計(jì)《解剖PetShop》系列之一前言:PetShop是一個(gè)范例,微軟用它來展示.Net企業(yè)系統(tǒng)開發(fā)的能力。業(yè)界有許多.Net與J2EE之爭,許多數(shù)據(jù)是從微軟的PetShop和Sun的PetStore而來。這種爭論不可避免帶有濃厚的商業(yè)色彩,對于我們開發(fā)人員而言,沒有必要過多關(guān)注。然而PetShop隨著版本的不斷更新,至現(xiàn)在基于.Net2.0的PetShop4.0為止,整個(gè)設(shè)計(jì)逐漸變得成熟而優(yōu)雅,卻又很多可以借鑒之處。PetShop是一個(gè)小型的項(xiàng)目,系統(tǒng)架構(gòu)與代碼都比較簡單,卻也凸現(xiàn)了許多頗有價(jià)值的設(shè)計(jì)與開發(fā)理念。本系列試圖對PetShop作一個(gè)全方位的解剖,依據(jù)的代碼是PetShop4.0,可以從鏈接/library/default.asp?url=/library/en-us/dnbda/html/bdasamppet4.asp中獲得。一、PetShop的系統(tǒng)架構(gòu)設(shè)計(jì)在軟件體系架構(gòu)設(shè)計(jì)中,分層式結(jié)構(gòu)是最常見,也是最重要的一種結(jié)構(gòu)。微軟推薦的分層式結(jié)構(gòu)一般分為三層,從下至上分別為:數(shù)據(jù)訪問層、業(yè)務(wù)邏輯層(又或成為領(lǐng)域?qū)樱⒈硎緦?,如圖所示:
圖一:三層的分層式結(jié)構(gòu)數(shù)據(jù)訪問層:有時(shí)候也稱為是持久層,其功能主要是負(fù)責(zé)數(shù)據(jù)庫的訪問。簡單的說法就是實(shí)現(xiàn)對數(shù)據(jù)表的Select,Insert,Update,Delete的操作。如果要加入ORM的元素,那么就會(huì)包括對象和數(shù)據(jù)表之間的mapping,以及對象實(shí)體的持久化。在PetShop的數(shù)據(jù)訪問層中,并沒有使用ORM,從而導(dǎo)致了代碼量的增加,可以看作是整個(gè)設(shè)計(jì)實(shí)現(xiàn)中的一大敗筆。業(yè)務(wù)邏輯層:是整個(gè)系統(tǒng)的核心,它與這個(gè)系統(tǒng)的業(yè)務(wù)(領(lǐng)域)有關(guān)。以PetShop為例,業(yè)務(wù)邏輯層的相關(guān)設(shè)計(jì),均和網(wǎng)上寵物店特有的邏輯相關(guān),例如查詢寵物,下訂單,添加寵物到購物車等等。如果涉及到數(shù)據(jù)庫的訪問,則調(diào)用數(shù)據(jù)訪問層。表示層:是系統(tǒng)的UI部分,負(fù)責(zé)使用者與整個(gè)系統(tǒng)的交互。在這一層中,理想的狀態(tài)是不應(yīng)包括系統(tǒng)的業(yè)務(wù)邏輯。表示層中的邏輯代碼,僅與界面元素有關(guān)。在PetShop中,是利用ASP.Net來設(shè)計(jì)的,因此包含了許多Web控件和相關(guān)邏輯。分層式結(jié)構(gòu)究竟其優(yōu)勢何在?MartinFowler在《PatternsofEnterpriseApplicationArchitecture》一書中給出了答案:
1、開發(fā)人員可以只關(guān)注整個(gè)結(jié)構(gòu)中的其中某一層;
2、可以很容易的用新的實(shí)現(xiàn)來替換原有層次的實(shí)現(xiàn);
3、可以降低層與層之間的依賴;
4、有利于標(biāo)準(zhǔn)化;
5、利于各層邏輯的復(fù)用。概括來說,分層式設(shè)計(jì)可以達(dá)至如下目的:分散關(guān)注、松散耦合、邏輯復(fù)用、標(biāo)準(zhǔn)定義。一個(gè)好的分層式結(jié)構(gòu),可以使得開發(fā)人員的分工更加明確。一旦定義好各層次之間的接口,負(fù)責(zé)不同邏輯設(shè)計(jì)的開發(fā)人員就可以分散關(guān)注,齊頭并進(jìn)。例如UI人員只需考慮用戶界面的體驗(yàn)與操作,領(lǐng)域的設(shè)計(jì)人員可以僅關(guān)注業(yè)務(wù)邏輯的設(shè)計(jì),而數(shù)據(jù)庫設(shè)計(jì)人員也不必為繁瑣的用戶交互而頭疼了。每個(gè)開發(fā)人員的任務(wù)得到了確認(rèn),開發(fā)進(jìn)度就可以迅速的提高。松散耦合的好處是顯而易見的。如果一個(gè)系統(tǒng)沒有分層,那么各自的邏輯都緊緊糾纏在一起,彼此間相互依賴,誰都是不可替換的。一旦發(fā)生改變,則牽一發(fā)而動(dòng)全身,對項(xiàng)目的影響極為嚴(yán)重。降低層與層間的依賴性,既可以良好地保證未來的可擴(kuò)展,在復(fù)用性上也是優(yōu)勢明顯。每個(gè)功能模塊一旦定義好統(tǒng)一的接口,就可以被各個(gè)模塊所調(diào)用,而不用為相同的功能進(jìn)行重復(fù)地開發(fā)。進(jìn)行好的分層式結(jié)構(gòu)設(shè)計(jì),標(biāo)準(zhǔn)也是必不可少的。只有在一定程度的標(biāo)準(zhǔn)化基礎(chǔ)上,這個(gè)系統(tǒng)才是可擴(kuò)展的,可替換的。而層與層之間的通信也必然保證了接口的標(biāo)準(zhǔn)化?!敖馃o足赤,人無完人”,分層式結(jié)構(gòu)也不可避免具有一些缺陷:
1、降低了系統(tǒng)的性能。這是不言而喻的。如果不采用分層式結(jié)構(gòu),很多業(yè)務(wù)可以直接造訪數(shù)據(jù)庫,以此獲取相應(yīng)的數(shù)據(jù),如今卻必須通過中間層來完成。
2、有時(shí)會(huì)導(dǎo)致級(jí)聯(lián)的修改。這種修改尤其體現(xiàn)在自上而下的方向。如果在表示層中需要增加一個(gè)功能,為保證其設(shè)計(jì)符合分層式結(jié)構(gòu),可能需要在相應(yīng)的業(yè)務(wù)邏輯層和數(shù)據(jù)訪問層中都增加相應(yīng)的代碼。前面提到,PetShop的表示層是用ASP.Net設(shè)計(jì)的,也就是說,它應(yīng)是一個(gè)BS系統(tǒng)。在.Net中,標(biāo)準(zhǔn)的BS分層式結(jié)構(gòu)如下圖所示:
圖二:.Net中標(biāo)準(zhǔn)的BS分層式結(jié)構(gòu)隨著PetShop版本的更新,其分層式結(jié)構(gòu)也在不斷的完善,例如PetShop2.0,就沒有采用標(biāo)準(zhǔn)的三層式結(jié)構(gòu),如圖三:
圖三:PetShop2.0的體系架構(gòu)從圖中我們可以看到,并沒有明顯的數(shù)據(jù)訪問層設(shè)計(jì)。這樣的設(shè)計(jì)雖然提高了數(shù)據(jù)訪問的性能,但也同時(shí)導(dǎo)致了業(yè)務(wù)邏輯層與數(shù)據(jù)訪問的職責(zé)混亂。一旦要求支持的數(shù)據(jù)庫發(fā)生變化,或者需要修改數(shù)據(jù)訪問的邏輯,由于沒有清晰的分層,會(huì)導(dǎo)致項(xiàng)目作大的修改。而隨著硬件系統(tǒng)性能的提高,以及充分利用緩存、異步處理等機(jī)制,分層式結(jié)構(gòu)所帶來的性能影響幾乎可以忽略不計(jì)。PetShop3.0糾正了此前層次不明的問題,將數(shù)據(jù)訪問邏輯作為單獨(dú)的一層獨(dú)立出來:
圖四:PetShop3.0的體系架構(gòu)PetShop4.0基本上延續(xù)了3.0的結(jié)構(gòu),但在性能上作了一定的改進(jìn),引入了緩存和異步處理機(jī)制,同時(shí)又充分利用了ASP.Net2.0的新功能MemberShip,因此PetShop4.0的系統(tǒng)架構(gòu)圖如下所示:
圖五:PetShop4.0的體系架構(gòu)比較3.0和4.0的系統(tǒng)架構(gòu)圖,其核心的內(nèi)容并沒有發(fā)生變化。在數(shù)據(jù)訪問層(DAL)中,仍然采用DALInterface抽象出數(shù)據(jù)訪問邏輯,并以DALFactory作為數(shù)據(jù)訪問層對象的工廠模塊。對于DALInterface而言,分別有支持MS-SQL的SQLServerDAL和支持Oracle的OracleDAL具體實(shí)現(xiàn)。而Model模塊則包含了數(shù)據(jù)實(shí)體對象。其詳細(xì)的模塊結(jié)構(gòu)圖如下所示:
圖六:數(shù)據(jù)訪問層的模塊結(jié)構(gòu)圖可以看到,在數(shù)據(jù)訪問層中,完全采用了“面向接口編程”思想。抽象出來的IDAL模塊,脫離了與具體數(shù)據(jù)庫的依賴,從而使得整個(gè)數(shù)據(jù)訪問層利于數(shù)據(jù)庫遷移。DALFactory模塊專門管理DAL對象的創(chuàng)建,便于業(yè)務(wù)邏輯層訪問。SQLServerDAL和OracleDAL模塊均實(shí)現(xiàn)IDAL模塊的接口,其中包含的邏輯就是對數(shù)據(jù)庫的Select,Insert,Update和Delete操作。因?yàn)閿?shù)據(jù)庫類型的不同,對數(shù)據(jù)庫的操作也有所不同,代碼也會(huì)因此有所區(qū)別。此外,抽象出來的IDAL模塊,除了解除了向下的依賴之外,對于其上的業(yè)務(wù)邏輯層,同樣僅存在弱依賴關(guān)系,如下圖所示:
圖七:業(yè)務(wù)邏輯層的模塊結(jié)構(gòu)圖圖七中BLL是業(yè)務(wù)邏輯層的核心模塊,它包含了整個(gè)系統(tǒng)的核心業(yè)務(wù)。在業(yè)務(wù)邏輯層中,不能直接訪問數(shù)據(jù)庫,而必須通過數(shù)據(jù)訪問層。注意圖中對數(shù)據(jù)訪問業(yè)務(wù)的調(diào)用,是通過接口模塊IDAL來完成的。既然與具體的數(shù)據(jù)訪問邏輯無關(guān),則層與層之間的關(guān)系就是松散耦合的。如果此時(shí)需要修改數(shù)據(jù)訪問層的具體實(shí)現(xiàn),只要不涉及到IDAL的接口定義,那么業(yè)務(wù)邏輯層就不會(huì)受到任何影響。畢竟,具體實(shí)現(xiàn)的SQLServerDAL和OracalDAL根本就與業(yè)務(wù)邏輯層沒有半點(diǎn)關(guān)系。因?yàn)樵赑etShop4.0中引入了異步處理機(jī)制。插入訂單的策略可以分為同步和異步,兩者的插入策略明顯不同,但對于調(diào)用者而言,插入訂單的接口是完全一樣的,所以PetShop4.0中設(shè)計(jì)了IBLLStrategy模塊。雖然在IBLLStrategy模塊中,僅僅是簡單的IOrderStategy,但同時(shí)也給出了一個(gè)范例和信息,那就是在業(yè)務(wù)邏輯的處理中,如果存在業(yè)務(wù)操作的多樣化,或者是今后可能的變化,均應(yīng)利用抽象的原理?;蛘呤褂媒涌?,或者使用抽象類,從而脫離對具體業(yè)務(wù)的依賴。不過在PetShop中,由于業(yè)務(wù)邏輯相對簡單,這種思想體現(xiàn)得不夠明顯。也正因?yàn)榇?,PetShop將核心的業(yè)務(wù)邏輯都放到了一個(gè)模塊BLL中,并沒有將具體的實(shí)現(xiàn)和抽象嚴(yán)格的按照模塊分開。所以表示層和業(yè)務(wù)邏輯層之間的調(diào)用關(guān)系,其耦合度相對較高:
圖八:表示層的模塊結(jié)構(gòu)圖在圖五中,各個(gè)層次中還引入了輔助的模塊,如數(shù)據(jù)訪問層的Messaging模塊,是為異步插入訂單的功能提供,采用了MSMQ(MicrosoftMessagingQueue)技術(shù)。而表示層的CacheDependency則提供緩存功能。這些特殊的模塊,我會(huì)在此后的文章中詳細(xì)介紹。PetShop數(shù)據(jù)訪問層之?dāng)?shù)據(jù)庫訪問設(shè)計(jì)《解剖PetShop》系列之二二、PetShop數(shù)據(jù)訪問層之?dāng)?shù)據(jù)庫訪問設(shè)計(jì)
在系列一中,我從整體上分析了PetShop的架構(gòu)設(shè)計(jì),并提及了分層的概念。從本部分開始,我將依次對各層進(jìn)行代碼級(jí)的分析,以求獲得更加細(xì)致而深入的理解。在PetShop4.0中,由于引入了ASP.Net2.0的一些新特色,所以數(shù)據(jù)層的內(nèi)容也更加的廣泛和復(fù)雜,包括:數(shù)據(jù)庫訪問、Messaging、MemberShip、Profile四部分。在系列二中,我將介紹有關(guān)數(shù)據(jù)庫訪問的設(shè)計(jì)。在PetShop中,系統(tǒng)需要處理的數(shù)據(jù)庫對象分為兩類:一是數(shù)據(jù)實(shí)體,對應(yīng)數(shù)據(jù)庫中相應(yīng)的數(shù)據(jù)表。它們沒有行為,僅用于表現(xiàn)對象的數(shù)據(jù)。這些實(shí)體類都被放到Model程序集中,例如數(shù)據(jù)表Order對應(yīng)的實(shí)體類OrderInfo,其類圖如下:
這些對象并不具有持久化的功能,簡單地說,它們是作為數(shù)據(jù)的載體,便于業(yè)務(wù)邏輯針對相應(yīng)數(shù)據(jù)表進(jìn)行讀/寫操作。雖然這些類的屬性分別映射了數(shù)據(jù)表的列,而每一個(gè)對象實(shí)例也恰恰對應(yīng)于數(shù)據(jù)表的每一行,但這些實(shí)體類卻并不具備對應(yīng)的數(shù)據(jù)庫訪問能力。由于數(shù)據(jù)訪問層和業(yè)務(wù)邏輯層都將對這些數(shù)據(jù)實(shí)體進(jìn)行操作,因此程序集Model會(huì)被這兩層的模塊所引用。第二類數(shù)據(jù)庫對象則是數(shù)據(jù)的業(yè)務(wù)邏輯對象。這里所指的業(yè)務(wù)邏輯,并非業(yè)務(wù)邏輯層意義上的領(lǐng)域(domain)業(yè)務(wù)邏輯(從這個(gè)意義上,我更傾向于將業(yè)務(wù)邏輯層稱為“領(lǐng)域邏輯層”),一般意義上說,這些業(yè)務(wù)邏輯即為基本的數(shù)據(jù)庫操作,包括Select,Insert,Update和Delete。由于這些業(yè)務(wù)邏輯對象,僅具有行為而與數(shù)據(jù)無關(guān),因此它們均被抽象為一個(gè)單獨(dú)的接口模塊IDAL,例如數(shù)據(jù)表Order對應(yīng)的接口IOrder:
將數(shù)據(jù)實(shí)體與相關(guān)的數(shù)據(jù)庫操作分離出來,符合面向?qū)ο蟮木?。首先,它體現(xiàn)了“職責(zé)分離”的原則。將數(shù)據(jù)實(shí)體與其行為分開,使得兩者之間依賴減弱,當(dāng)數(shù)據(jù)行為發(fā)生改變時(shí),并不影響Model模塊中的數(shù)據(jù)實(shí)體對象,避免了因一個(gè)類職責(zé)過多、過大,從而導(dǎo)致該類的引用者發(fā)生“災(zāi)難性”的影響。其次,它體現(xiàn)了“抽象”的精神,或者說是“面向接口編程”的最佳體現(xiàn)。抽象的接口模塊IDAL,與具體的數(shù)據(jù)庫訪問實(shí)現(xiàn)完全隔離。這種與實(shí)現(xiàn)無關(guān)的設(shè)計(jì),保證了系統(tǒng)的可擴(kuò)展性,同時(shí)也保證了數(shù)據(jù)庫的可移植性。在PetShop中,可以支持SQLServer和Oracle,那么它們具體的實(shí)現(xiàn)就分別放在兩個(gè)不同的模塊SQLServerDAL、OracleDAL中。以O(shè)rder為例,在SQLServerDAL、OracleDAL兩個(gè)模塊中,有不同的實(shí)現(xiàn),但它們同時(shí)又都實(shí)現(xiàn)了IOrder接口,如圖:
從數(shù)據(jù)庫的實(shí)現(xiàn)來看,PetShop體現(xiàn)出了沒有ORM框架的臃腫與丑陋。由于要對數(shù)據(jù)表進(jìn)行Insert和Select操作,以SQLServer為例,就使用了SqlCommand,SqlParameter,SqlDataReader等對象,以完成這些操作。尤其復(fù)雜的是Parameter的傳遞,在PetShop中,使用了大量的字符串常量來保存參數(shù)的名稱。此外,PetShop還專門為SQLServer和Oracle提供了抽象的Helper類,包裝了一些常用的操作,如ExecuteNonQuery、ExecuteReader等方法。在沒有ORM的情況下,使用Helper類是一個(gè)比較好的策略,利用它來完成數(shù)據(jù)庫基本操作的封裝,可以減少很多和數(shù)據(jù)庫操作有關(guān)的代碼,這體現(xiàn)了對象復(fù)用的原則。PetShop將這些Helper類統(tǒng)一放到DBUtility模塊中,不同數(shù)據(jù)庫的Helper類暴露的方法基本相同,只除了一些特殊的要求,例如Oracle中處理bool類型的方式就和SQLServer不同,從而專門提供了OraBit和OraBool方法。此外,Helper類中的方法均為static方法,以利于調(diào)用。OracleHelper的類圖如下:
對于數(shù)據(jù)訪問層來說,最頭疼的是SQL語句的處理。在早期的CS結(jié)構(gòu)中,由于未采用三層式架構(gòu)設(shè)計(jì),數(shù)據(jù)訪問層和業(yè)務(wù)邏輯層是緊密糅合在一起的,因此,SQL語句遍布與系統(tǒng)的每一個(gè)角落。這給程序的維護(hù)帶來極大的困難。此外,由于Oracle使用的是PL-SQL,而SQLServer和Sybase等使用的是T-SQL,兩者雖然都遵循了標(biāo)準(zhǔn)SQL的語法,但在很多細(xì)節(jié)上仍有區(qū)別,如果將SQL語句大量的使用到程序中,無疑為可能的數(shù)據(jù)庫移植也帶來了困難。最好的方法是采用存儲(chǔ)過程。這種方法使得程序更加整潔,此外,由于存儲(chǔ)過程可以以數(shù)據(jù)庫腳本的形式存在,也便于移植和修改。但這種方式仍然有缺陷。一是存儲(chǔ)過程的測試相對困難。雖然有相應(yīng)的調(diào)試工具,但比起對代碼的調(diào)試而言,仍然比較復(fù)雜且不方便。二是對系統(tǒng)的更新帶來障礙。如果數(shù)據(jù)庫訪問是由程序完成,在.Net平臺(tái)下,我們僅需要在修改程序后,將重新編譯的程序集xcopy到部署的服務(wù)器上即可。如果使用了存儲(chǔ)過程,出于安全的考慮,必須有專門的DBA重新運(yùn)行存儲(chǔ)過程的腳本,部署的方式受到了限制。我曾經(jīng)在一個(gè)項(xiàng)目中,利用一個(gè)專門的表來存放SQL語句。如要使用相關(guān)的SQL語句,就利用關(guān)鍵字搜索獲得對應(yīng)語句。這種做法近似于存儲(chǔ)過程的調(diào)用,但卻避免了部署上的問題。然而這種方式卻在性能上無法得到保證。它僅適合于SQL語句較少的場景。不過,利用良好的設(shè)計(jì),我們可以為各種業(yè)務(wù)提供不同的表來存放SQL語句。同樣的道理,這些SQL語句也可以存放到XML文件中,更有利于系統(tǒng)的擴(kuò)展或修改。不過前提是,我們需要為它提供專門的SQL語句管理工具。SQL語句的使用無法避免,如何更好的應(yīng)用SQL語句也無定論,但有一個(gè)原則值得我們遵守,就是“應(yīng)該盡量讓SQL語句盡存在于數(shù)據(jù)訪問層的具體實(shí)現(xiàn)中”。當(dāng)然,如果應(yīng)用ORM,那么一切就變得不同了。因?yàn)镺RM框架已經(jīng)為數(shù)據(jù)訪問提供了基本的Select,Insert,Update和Delete操作了。例如在NHibernate中,我們可以直接調(diào)用ISession對象的Save方法,來Insert(或者說是Create)一個(gè)數(shù)據(jù)實(shí)體對象:
publicvoidInsert(OrderInfoorder)
{
ISessions=Sessions.GetSession();
ITransactiontrans=null;
try
{
trans=s.BeginTransaction();
s.Save(order);
trans.Commit();
}
finally
{
s.Close();
}
}沒有SQL語句,也沒有那些煩人的Parameters,甚至不需要專門去考慮事務(wù)。此外,這樣的設(shè)計(jì),也是與數(shù)據(jù)庫無關(guān)的,NHibernate可以通過Dialect(方言)的機(jī)制支持不同的數(shù)據(jù)庫。唯一要做的是,我們需要為OrderInfo定義hbm文件。當(dāng)然,ORM框架并非是萬能的,面對紛繁復(fù)雜的業(yè)務(wù)邏輯,它并不能完全消滅SQL語句,以及替代復(fù)雜的數(shù)據(jù)庫訪問邏輯,但它卻很好的體現(xiàn)了“80/20(或90/10)法則”(也被稱為“帕累托法則”),也就是說:花比較少(10%-20%)的力氣就可以解決大部分(80%-90%)的問題,而要解決剩下的少部分問題則需要多得多的努力。至少,那些在數(shù)據(jù)訪問層中占據(jù)了絕大部分的CRUD操作,通過利用ORM框架,我們就僅需要付出極少數(shù)時(shí)間和精力來解決它們了。這無疑縮短了整個(gè)項(xiàng)目開發(fā)的周期。還是回到對PetShop的討論上來?,F(xiàn)在我們已經(jīng)有了數(shù)據(jù)實(shí)體,數(shù)據(jù)對象的抽象接口和實(shí)現(xiàn),可以說有關(guān)數(shù)據(jù)庫訪問的主體就已經(jīng)完成了。留待我們的還有兩個(gè)問題需要解決:
1、數(shù)據(jù)對象創(chuàng)建的管理
2、利于數(shù)據(jù)庫的移植在PetShop中,要?jiǎng)?chuàng)建的數(shù)據(jù)對象包括Order,Product,Category,Inventory,Item。在前面的設(shè)計(jì)中,這些對象已經(jīng)被抽象為對應(yīng)的接口,而其實(shí)現(xiàn)則根據(jù)數(shù)據(jù)庫的不同而有所不同。也就是說,創(chuàng)建的對象有多種類別,而每種類別又有不同的實(shí)現(xiàn),這是典型的抽象工廠模式的應(yīng)用場景。而上面所述的兩個(gè)問題,也都可以通過抽象工廠模式來解決。標(biāo)準(zhǔn)的抽象工廠模式類圖如下:
例如,創(chuàng)建SQLServer的Order對象如下:
PetShopFactoryfactory=newSQLServerFactory();
IOrder=factory.CreateOrder();要考慮到數(shù)據(jù)庫的可移植性,則factory必須作為一個(gè)全局變量,并在主程序運(yùn)行時(shí)被實(shí)例化。但這樣的設(shè)計(jì)雖然已經(jīng)達(dá)到了“封裝變化”的目的,但在創(chuàng)建PetShopFactory對象時(shí),仍不可避免的出現(xiàn)了具體的類SQLServerFactory,也即是說,程序在這個(gè)層面上產(chǎn)生了與SQLServerFactory的強(qiáng)依賴。一旦整個(gè)系統(tǒng)要求支持Oracle,那么還需要修改這行代碼為:
PetShopFactoryfactory=newOracleFactory();修改代碼的這種行為顯然是不可接受的。解決的辦法是“依賴注入”?!耙蕾囎⑷搿钡墓δ芡ǔJ怯脤iT的IoC容器提供的,在Java平臺(tái)下,這樣的容器包括Spring,PicoContainer等。而在.Net平臺(tái)下,最常見的則是Spring.Net。不過,在PetShop系統(tǒng)中,并不需要專門的容器來實(shí)現(xiàn)“依賴注入”,簡單的做法還是利用配置文件和反射功能來實(shí)現(xiàn)。也就是說,我們可以在web.config文件中,配置好具體的Factory對象的完整的類名。然而,當(dāng)我們利用配置文件和反射功能時(shí),具體工廠的創(chuàng)建就顯得有些“畫蛇添足”了,我們完全可以在配置文件中,直接指向具體的數(shù)據(jù)庫對象實(shí)現(xiàn)類,例如PetShop.SQLServerDAL.IOrder。那么,抽象工廠模式中的相關(guān)工廠就可以簡化為一個(gè)工廠類了,所以我將這種模式稱之為“具有簡單工廠特質(zhì)的抽象工廠模式”,其類圖如下:
DataAccess類完全取代了前面創(chuàng)建的工廠類體系,它是一個(gè)sealed類,其中創(chuàng)建各種數(shù)據(jù)對象的方法,均為靜態(tài)方法。之所以能用這個(gè)類達(dá)到抽象工廠的目的,是因?yàn)榕渲梦募头瓷涞倪\(yùn)用,如下的代碼片斷所示:
publicsealedclassDataAccess
{
//LookuptheDALimplementationweshouldbeusing
privatestaticreadonlystringpath=ConfigurationManager.AppSettings[”WebDAL”];
privatestaticreadonlystringorderPath=ConfigurationManager.AppSettings[”O(jiān)rdersDAL”];
publicstaticPetShop.IDAL.IOrderCreateOrder()
{
stringclassName=orderPath+“.Order”;
return(PetShop.IDAL.IOrder)Assembly.Load(orderPath).CreateInstance(className);
}
}在PetShop中,這種依賴配置文件和反射創(chuàng)建對象的方式極其常見,包括IBLLStategy、CacheDependencyFactory等等。這些實(shí)現(xiàn)邏輯散布于整個(gè)PetShop系統(tǒng)中,在我看來,是可以在此基礎(chǔ)上進(jìn)行重構(gòu)的。也就是說,我們可以為整個(gè)系統(tǒng)提供類似于“ServiceLocator”的實(shí)現(xiàn):
publicstaticclassServiceLocator
{
privatestaticreadonlystringdalPath=ConfigurationManager.AppSettings[”WebDAL”];
privatestaticreadonlystringorderPath=ConfigurationManager.AppSettings[”O(jiān)rdersDAL”];
//……
pr
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年中國電加熱管行業(yè)市場全景評(píng)估及發(fā)展戰(zhàn)略研究報(bào)告
- 江南機(jī)械環(huán)評(píng)報(bào)告表
- 2022-2027年中國香油(芝麻油)市場競爭格局及行業(yè)投資潛力預(yù)測報(bào)告
- 尾礦庫安全生產(chǎn)費(fèi)用提取標(biāo)準(zhǔn)
- 2025年中國套筒導(dǎo)向調(diào)節(jié)閥行業(yè)市場發(fā)展前景及發(fā)展趨勢與投資戰(zhàn)略研究報(bào)告
- 2025年安全檢查總結(jié)報(bào)告
- 2025年中國白蘭地行業(yè)市場調(diào)查研究及投資前景預(yù)測報(bào)告
- 道路運(yùn)輸安全員招聘
- 項(xiàng)目部安全生產(chǎn)管理規(guī)章制度
- 2025年國際機(jī)場擴(kuò)建工程項(xiàng)目可行性研究報(bào)告
- 剖宮產(chǎn)手術(shù)專家共識(shí)2023年解讀
- 2024-2025學(xué)年廣東省惠州市惠城區(qū)七年級(jí)下學(xué)期期末數(shù)學(xué)教學(xué)質(zhì)量監(jiān)測試題(含答案)
- 2025年上半年駐村工作總結(jié)范例(三篇)
- 樓宇自控系統(tǒng)入門基礎(chǔ)知識(shí)
- 化工企業(yè)安全操作規(guī)程培訓(xùn)計(jì)劃
- 氣管插管堵塞的原因分析課件
- 2025年南昌市產(chǎn)業(yè)投資集團(tuán)招聘筆試參考題庫含答案解析
- 熱氣球晚會(huì)活動(dòng)方案
- 2024氣爆震源操作流程及HSE風(fēng)險(xiǎn)評(píng)估標(biāo)準(zhǔn)
- 銀行培訓(xùn)課件:客戶投訴處理
- 【MOOC】結(jié)構(gòu)力學(xué)-武漢理工大學(xué) 中國大學(xué)慕課MOOC答案
評(píng)論
0/150
提交評(píng)論