系统架构师-基础到企业应用架构-服务层
一、上章回顧
??????? 上篇我們主要講解了系統(tǒng)架構(gòu)中的四種架構(gòu)模式,并且分析了四種架構(gòu)模式的實現(xiàn)及應(yīng)用場景,那么先來回顧下架構(gòu)中的業(yè)務(wù)邏輯層的使用及總結(jié)。
?????????如果大家對圖中講述的內(nèi)容不明白或者說是不深入那么可以參考上篇講
解的內(nèi)容:系統(tǒng)架構(gòu)師-基礎(chǔ)到企業(yè)應(yīng)用架構(gòu)-業(yè)務(wù)邏輯層。
二、摘要
??????? 本文將已架構(gòu)的方式去分析分層結(jié)構(gòu)中的服務(wù)層的設(shè)計,如何設(shè)計出來滿足我們說的業(yè)務(wù)需求及設(shè)計規(guī)范的服務(wù)層將是我們的目標,可能我想大家在項目架構(gòu)的
過程中可能有些同仁,沒有用到該層,或者說是采用的是常用的分層結(jié)構(gòu)的設(shè)計,而沒有把服務(wù)層單獨的抽出來,當然我們必須首先知道服務(wù)層是干什么用的?為什么
要單獨寫一個服務(wù)層呢?還有就是設(shè)計服務(wù)層我們從哪些方面入手呢?及怎么判定一個服務(wù)層設(shè)計的好壞呢?這些都是本章要講解的具體內(nèi)容,當然本文中的內(nèi)容都是
本人平時在項目中的一些經(jīng)驗,可能在一些有豐富經(jīng)驗設(shè)計的大牛面前,我講解的都是皮毛,但是我抱著能給初學(xué)者指引和為已知者溫習(xí)的目的而寫,錯誤之處再所難
免,請大家提出寶貴意見和建議。本文講述以下內(nèi)容:
?????????下面我們將針對上面的問題分別進行講述。
三、本章大綱
?????? 1、上章回顧。
?????? 2、摘要。
?????? 3、本章大綱。
?????? 4、服務(wù)層的介紹。
?????? 5、服務(wù)層實戰(zhàn)。
?????? 6、本章總結(jié)。
?????? 7、系列進度。
?????? 8、下篇預(yù)告。
四、服務(wù)層的介紹
??????? 本節(jié)中將會對服務(wù)層的設(shè)計進行詳細的分析。我們知道我們現(xiàn)在在軟件開發(fā)的過程中,通常我們會將一些業(yè)務(wù)邏輯的代碼寫在表現(xiàn)層,當然這樣的方式不是不允
許,當然一般情況下來說我們感覺沒什么,但是采用這樣的方式,那么表現(xiàn)層與業(yè)務(wù)邏輯層之間的關(guān)系是耦合性的,可能我們是屬于那種希望設(shè)計簡潔或者說對設(shè)計規(guī)
范嚴格要求的時候,那么我們就可以考慮將業(yè)務(wù)邏輯的組織通過服務(wù)層來實現(xiàn),那么服務(wù)層的作用就是將表現(xiàn)層與業(yè)務(wù)邏輯層之間完成解耦。那么表現(xiàn)層中就不會出現(xiàn)
任何的業(yè)務(wù)代碼,當然這樣帶來的好處也是顯而易見的,就是當我們修改業(yè)務(wù)層代碼時,我們不需要修改表現(xiàn)層的代碼,當然如果服務(wù)層設(shè)計的不好,那么可能會造成
反效果。
??????? 服務(wù)層是干什么的? 通過上面的簡單介紹,我想大家都對服務(wù)層有了個簡單的認識,那么下面我們還是通過圖形的方式來看看服務(wù)層的位置及作用吧,可能那樣
更容易理解。
?????????這幾層之間都是通過數(shù)據(jù)傳輸對象來完成各層之間的數(shù)據(jù)通信。通過上圖我們知道,服務(wù)層是通過數(shù)據(jù)傳輸對象
與業(yè)務(wù)邏輯層直接進行交互,那么業(yè)務(wù)邏輯層與服務(wù)層具體交互的方式及內(nèi)容是什么呢?
??????? 下面我們來看看,業(yè)務(wù)邏輯層中的四種模式在服務(wù)層中的表現(xiàn)。
?????????
???????? 下面我們來舉例說明服務(wù)層的作用。通過表現(xiàn)層與業(yè)務(wù)邏輯的解耦來說明服務(wù)層的作用。我們還是以B2C中的購物流程來說。
???????? 我們先以購物流程中的添加產(chǎn)品到購物車來說
??????????可以簡單的看作下面幾個對象之間的交互,首先我們先要選擇產(chǎn)品,然后將產(chǎn)品添加到購物車
中,然后當然這個購物車是某個會員登陸以后的購物清單,一個購物車中可能有多個產(chǎn)品。我們來看看代碼可能如下:
???????? 我們定義的產(chǎn)品信息如下:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /// <summary> /// 產(chǎn)品信息 /// </summary> public?class?Product { ????/// <summary> ????/// 返回所有的產(chǎn)品信息 ????/// </summary> ????/// <returns></returns> ????public?List<Product> GetAll() ????{ ????????return?new?List<Product>(); ????} ????/// <summary> ????/// 返回產(chǎn)品信息根據(jù)產(chǎn)品ID ????/// </summary> ????/// <returns></returns> ????public?Product GetByID(int?ID) ????{ ????????return?new?Product(); ????} } |
??????? 產(chǎn)品信息中包含2個方法,一個是獲取所有產(chǎn)品的列表,還有一個是獲取實體的信息根據(jù)主鍵。我們來看看購物車的代碼:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /// <summary> /// 購物車 /// </summary> public?class?ShopCar { ????/// <summary> ????/// 購物車中的產(chǎn)品 ????/// </summary> ????Dictionary<int, Product> products = new?Dictionary<int, Product>(); ????/// <summary> ????/// 將指定產(chǎn)品ID的產(chǎn)品添加到購物車 ????/// </summary> ????public?bool?Add(int?ID) ????{ ????????Product product = new?Product(); ????????product= product.GetByID(ID); ????????if?(products.ContainsKey(ID)) ????????????return?false; ????????products.Add(ID,product); ????????return?true; ????} } ?下面我們來看看前臺調(diào)用的代碼: ?public?class?ShopCar { ????/// <summary> ????/// 將指定產(chǎn)品ID的產(chǎn)品添加到購物車 ????/// </summary> ????public?bool?Add(int?ID) ????{ ????????ShopCar cart = new?ShopCar(); ????????return?cart.Add(ID); ????} } |
??????? 上面的代碼引用了ShopCar對象,說明UI層的ShopCar與業(yè)務(wù)層的ShopCar 有依賴關(guān)系,那么我們?nèi)绾谓怦钅?#xff1f;通過引入第三方類,來實現(xiàn)依賴的解除。具體
的代碼如下:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public?class?ShopCar { ????/// <summary> ????/// 將指定產(chǎn)品ID的產(chǎn)品添加到購物車 ????/// </summary> ????public?bool?Add(int?ID) ????{ ????????IShopCar car; ????????CarFactory factory = new?CarFactory(); ????????car = factory.ShopCarFactory(); ????????car.Add(ID); ????????return?true; ????} } |
?????? 修改后通過服務(wù)層中的購物車工廠構(gòu)造出購物車實例,這樣就可以把業(yè)務(wù)邏輯層與界面層之間的耦合關(guān)系通過新增加一個服務(wù)層來實現(xiàn)解耦,那么表現(xiàn)層的代碼更
簡介,也符合設(shè)計規(guī)范。
?????? 其實我們這里的服務(wù)只是講述了服務(wù)層的簡單應(yīng)用場景,其實具體的服務(wù)層在使用的過程中遠比我們前面講解的復(fù)雜,首先可能服務(wù)層還會與數(shù)據(jù)訪問層直接交
互,比如說操作數(shù)據(jù)庫,持久化等,服務(wù)層主要是組織業(yè)務(wù)邏輯中的業(yè)務(wù)邏輯組件,服務(wù)層還通過ORM框架中提供的數(shù)據(jù)庫訪問服務(wù)完成相應(yīng)的操作。我們前面講過,
一般情況下,表現(xiàn)層與服務(wù)層交互是,都是通過數(shù)據(jù)傳輸對象來進行通信的,那么顯然有時候我們需要在服務(wù)層做處理,將數(shù)據(jù)傳輸對象轉(zhuǎn)換成領(lǐng)域模型,當然有時候
我們在設(shè)計系統(tǒng)架構(gòu)時,如果系統(tǒng)中的領(lǐng)域模型較多,或者說是拆分后的數(shù)據(jù)傳輸對象太多時,我們只要將一個領(lǐng)域模型對應(yīng)一個數(shù)據(jù)傳輸對象就好,只不過是把領(lǐng)域
模型中的行為省略而已。
??????? 我們來看看目前比較流行的關(guān)于服務(wù)層的認識:
??????? 我想目前最流行的關(guān)于服務(wù)層的架構(gòu)就是SOA(面向服務(wù)架構(gòu)),可以說是SOA的出現(xiàn)才讓服務(wù)層流行起來,SOA中對服務(wù)的理解是這樣的,服務(wù)層是提供一系
列的服務(wù),而具體的業(yè)務(wù)流程是通過一系列的服務(wù)組成的,把服務(wù)看作不是面向某種特定的技術(shù),而是業(yè)務(wù)流程的組織方式。達到的目的是,提供了一系列的服務(wù),只
需要配置組織服務(wù)的流程,就可以不管什么樣的技術(shù),都能滿足要求的業(yè)務(wù)流程。當然這是理想化的形式,具體的實行起來還是有相當大的難度。
?????? 其實我們可以這樣想象,服務(wù)就是一個提供了API的類,通過封裝,外界訪問服務(wù)時只能通過服務(wù)提供的接口來訪問。
????????例如我們通過服務(wù)層提供上述的四種服務(wù),然后在表現(xiàn)層中通過
服務(wù)層中的服務(wù)的調(diào)用來完成相應(yīng)的功能,比如我們在表現(xiàn)層中有新紀錄添加時,我們通過服務(wù)層的添加記錄的方法來完成,服務(wù)層通過提供的服務(wù)直接完成相應(yīng)的準備
工作,并且這些服務(wù)在定義時都是通過接口的方式來向外提供功能,因此只要滿足接口契約就可以完成組件的替換工作,而不會影響系統(tǒng)的運行。
??????? 我們有的時候有這樣的需求,我們的軟件程序要求既有B/S的形式直接通過瀏覽器來完成應(yīng)用,有時候還需要C/S客戶端的形式訪問系統(tǒng)的功能,這時候我們?nèi)绻?/p>
通過服務(wù)來組織業(yè)務(wù)邏輯那么我們只需要寫一個服務(wù)層就可以完成遠程服務(wù)訪問,而不用B/S下寫一次業(yè)務(wù)邏輯調(diào)用,然后C/S下再寫一次,而且這樣一旦修改了相應(yīng)的
業(yè)務(wù)邏輯,那么我們需要變動的代價很大。我們來看看服務(wù)層給我們提供了什么。
?????????通過服務(wù)層我們可以不關(guān)心業(yè)務(wù)邏輯的實現(xiàn),我們在用戶圖形
化界面中只需要訪問相關(guān)的服務(wù)即可,舉個簡單例子,就行銀行的銀聯(lián),跨行取款的行為。下面可以簡單的描述了用戶取款的服務(wù)。
?????????上面簡單的描述了,用戶的取款服
務(wù),當然只要是銀聯(lián)的銀行卡,都可以享受到跨行的異地取款,當然不管什么卡,提供給用戶的服務(wù)都是相同的。當然我們這里說的是C/S客戶端服務(wù)這樣的要求,當
然如果說是B/S架構(gòu)的形式,那么可能我們不用單獨抽出這樣的遠程服務(wù)的形式。而服務(wù)層可能就是表現(xiàn)層的一部分,這時候我們建議不要把服務(wù)層設(shè)計成web服務(wù),這
時候我們設(shè)計服務(wù)層時更關(guān)心服務(wù)層的抽象,而不是實現(xiàn)方式。
?????? 一般情況下來說服務(wù)層的設(shè)計實現(xiàn),可能有時候和部署時的要求有關(guān),例如有時候我們需要將服務(wù)部署在應(yīng)用服務(wù)器上,這時候我們就必須考慮服務(wù)層必須發(fā)布成
遠程調(diào)用服務(wù)或者Web服務(wù),當然具體的遠程調(diào)用服務(wù)可以有幾種方式,我們主要看基于什么通信方式,是remoting還是soap,還是socket通信等。
??????? 當然有時候我們對服務(wù)分為二種類型,粗粒度的服務(wù)與細粒度的服務(wù),那么我們怎么理解它呢?其實說白了粗粒度的服務(wù)就是某個大的服務(wù),而細粒度的就是大
的服務(wù)內(nèi)部的子服務(wù)。可以這樣理解,粗粒度是按照用例來組織操作的,例如我們上面的銀行取款服務(wù),那么粗粒度的服務(wù)就看作這樣的流程,用戶插卡-輸入密碼-取
款-退卡。而細粒度的服務(wù)關(guān)系的是:檢查用戶賬戶,余額的轉(zhuǎn)換等,包括一些比較詳細的,密碼的驗證等等,這些都是細粒度的服務(wù),可以把粗粒度看作某個用例的大
的業(yè)務(wù)操作,對領(lǐng)域中的對象不關(guān)心,只關(guān)心領(lǐng)域模型中的交互。細粒度可以看作領(lǐng)域模型中的具體對象及對象的行為。
?????? 接下來我們將講述服務(wù)層常用的幾種架構(gòu)模式:
????????第五節(jié)中將會詳細的講述每種模式及模式直接的區(qū)別及應(yīng)用。
?????? 我們來看看服務(wù)層的應(yīng)用場景及什么情況下使用服務(wù)層?
?????? 一般來說服務(wù)層適合企業(yè)應(yīng)用系統(tǒng)中,也適合多層系統(tǒng)中,特別是業(yè)務(wù)邏輯比較復(fù)雜的系統(tǒng)程序中,如果說應(yīng)用程序在多中形式的終端上使用時,推薦使用服務(wù)
層,當然如果你的系統(tǒng)中只有一種類型的前端表現(xiàn)形式時,例如Web應(yīng)用程序,只有一個前端要求時,例如通過瀏覽器訪問的形式,并且業(yè)務(wù)邏輯層能夠很好的與表現(xiàn)層交互時,那么如果我們還把業(yè)務(wù)邏輯與表現(xiàn)層直接的通信抽出來通過服
務(wù)層來完成的話,那么服務(wù)層只是完成任務(wù)的轉(zhuǎn)發(fā),并沒有實際行的好處及減少開銷,那么此時不推薦使用服務(wù)層。
?????? 我們來總結(jié)下服務(wù)層的優(yōu)勢與劣勢,已衡量我們在系統(tǒng)中使用服務(wù)層的必要性:
???????
五、服務(wù)層實戰(zhàn)
??????? 前面已經(jīng)講述了服務(wù)層的優(yōu)缺點及應(yīng)用場景的介紹,那么我們本節(jié)中將要詳細的講解服務(wù)層設(shè)計的幾種模式,主要是體現(xiàn)出服務(wù)層設(shè)計實現(xiàn)的幾個思路,方便我
們在項目的實踐過程中少走彎路。為我們的系統(tǒng)帶來更好的適應(yīng)性及擴展性要求。我們閑來將第一類模式
?????????裝飾模式在服務(wù)層的含義,跟設(shè)計模式中的裝飾模式可以說是有著異曲同工之妙,就是將服務(wù)層的一系列方法包裝成干凈
的接口,以供外部調(diào)用,通過該模式,我們能夠?qū)⒓毩6鹊姆?wù)包裝成粗粒度的服務(wù),這樣可以更方便的為表現(xiàn)層服務(wù),并且可以通過裝飾模式將服務(wù)包裝成遠程調(diào)用
服務(wù)的方式,具體內(nèi)部的實現(xiàn)都不是主要的關(guān)注點,對客戶來說,他們可以以統(tǒng)一的方式不管客戶端的形式是怎么樣的。
??????? 我們都知道面向?qū)ο蟮脑O(shè)計原則是要求某個對象功能單一,盡可能的簡單,但是通常我們在表現(xiàn)層中的一些業(yè)務(wù)流程中要求有多個實體之間進行交互時,那么我
們通過服務(wù)來組織就會顯得比較好,我們通過裝飾模式來實現(xiàn)這樣的業(yè)務(wù)要求就會比較好,我們將一系列細粒度比較復(fù)雜的業(yè)務(wù)邏輯放在一個服務(wù)的API方法中,表現(xiàn)層
通過調(diào)用這個方法來完成復(fù)雜的業(yè)務(wù)邏輯交互。
??????? 服務(wù)層中的裝飾模式更關(guān)心的是如何為表現(xiàn)層提供更好的服務(wù),隱藏內(nèi)部的細節(jié),下面我們來看看相關(guān)的例子吧,我們這里還是以購物流程來說吧。
?????????購物流程的簡單流程可能如此,那么當然我們在購物流程中還有其他的服務(wù),比如我們在購物的過程中的
短信提醒給賣家,或者說是發(fā)送郵件給賣家。等這些是我們系統(tǒng)提供的服務(wù),包括一些日志性的服務(wù)。那么這些我們?nèi)绾稳プ瞿?#xff1f;當然在上面的流程中,用戶只需要關(guān)
系最后的一步,提交訂單,付款的環(huán)節(jié),當用戶付款后會給用戶發(fā)送短信,那么顯然我們在服務(wù)中就可以把下單的過程中默認提供系統(tǒng)日志,系統(tǒng)安全,權(quán)限等等問題
一并處理,而給客戶提供的方法則只包含支付的接口。
?| 1 2 3 4 5 6 7 8 | public?interface?IPay ?{ ?????/// <summary> ?????/// 支付接口 ?????/// </summary> ?????/// <param name="product"></param> ?????void?Pay(Rule.Product product); } |
???? 上面我們定義了支付的接口,來看業(yè)務(wù)層中的訂單操作:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public?class?Order { ????/// <summary> ????/// 添加產(chǎn)品 ????/// </summary> ????/// <returns></returns> ????public?int?Add(Product product) ????{ ????????return?0; ????} ????/// <summary> ????/// 保存 ????/// </summary> ????/// <returns></returns> ????public?int?Save() ????{ ????????return?0; ????} ????/// <summary> ????/// 刪除 ????/// </summary> ????/// <returns></returns> ????public?int?Delete() ????{ ????????return?0; ????} ????/// <summary> ????/// 更新 ????/// </summary> ????/// <returns></returns> ????public?int?Update() ????{ ????????return?0; ????} } |
???? 我們來看看服務(wù)類中接口的實現(xiàn):
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public?class?Pay : IPay { ????public?bool?PayMent(Rule.Product product) ????{ ????????//具體的下單操作 ????????Rule.Order order = new?Rule.Order(); ????????//持久化操作 ????????order.Add(product); ????????//發(fā)送手機短信,發(fā)送給賣家,通知有人買什么產(chǎn)品等 ????????SendMessage.Instance.SendMsg(string.Empty, string.Empty); ????????return?true; ????} ????#region IPay 成員 ????public?void?IPay.Pay(Rule.Product product) ????{ ????????this.PayMent(product); ????} ????#endregion } |
???? 那么上面我們在服務(wù)層組合多個簡單的服務(wù)提供給一個方法,那么UI層只要簡單的調(diào)用服務(wù)層接口中提供的方法即可,就能完成服務(wù)的調(diào)用。我們來看看UI層的代碼
?| 1 2 3 4 5 6 7 8 9 10 11 | public?class?Order { ????public?void?Pay() ????{ ????????Service.PayFactory factory=new?Service.PayFactory(); ????????//調(diào)用服務(wù)層中的支付 ????????Service.IPay pay = factory.CreatePay(); ????????//這里只是測試,所以沒有屏蔽New的代碼 ????????pay.Pay(new?Rule.Product()); ????} } |
????? 那么通過上面的簡單形式我們就完成了一個簡單的裝飾模式的服務(wù)層的設(shè)計,是不是很簡單呢?可能看起來代碼有點多,不過這樣的設(shè)計很利于我們在后期的擴展
性和適應(yīng)性,特別是等到系統(tǒng)的功能更復(fù)雜更多時。好的設(shè)計就能體現(xiàn)出它的價值了。
????? 當然上面我們通過了直接使用領(lǐng)域模型中的對象作為數(shù)據(jù)傳輸,當然我們可以通過數(shù)據(jù)傳輸對象的自定義對象來完成,情況更好,我這里就不舉例說明了,下面我
們來講述下一個模式:傳輸對象模式。?那么我們前面也講過了數(shù)據(jù)傳輸對象,其實這個模式只是講解了數(shù)據(jù)傳輸對象的用法。
????? 傳輸對象模式:
????? 該模式主要是針對系統(tǒng)中各分層之間的數(shù)據(jù)傳輸模式的設(shè)計,通過傳輸對象可以降低各層之間分發(fā)數(shù)據(jù)的次數(shù),提高系統(tǒng)性能,通常來說該模式非常有用。但是也
有它的弊端。比如說當領(lǐng)域模型太多的時候,如果把領(lǐng)域模型中的每個對象的數(shù)據(jù)載體,都設(shè)計成傳輸對象,那么系統(tǒng)將是一個非常龐大的工程,因為過度設(shè)計,讓系
統(tǒng)難于維護與控制。我們來總結(jié)下使用該模式的優(yōu)缺點:
??????
????? 那么有優(yōu)點肯定就有缺點,我們來看看傳輸對象可能帶來的劣勢:
??????
????? 現(xiàn)在目前我們在使用數(shù)據(jù)傳輸對象的時候,都必須手動的去維護及創(chuàng)建,目前沒有比較好的工具去完成自動創(chuàng)建的功能。比如說能將同一個對象,根據(jù)不同UI的需
求自動的將一些屬性屏蔽或者啟用等。可能通過XML配置文件來完成會是可行的方案,不過目前還沒有一個比較好的工具去自動的根據(jù)領(lǐng)域模型中的對象自動的創(chuàng)建傳
輸對象,然后還能提供這個傳輸對象根據(jù)不同UI界面要求完成不同的自定義配置功能,希望各位如果了解的可以給小弟指點下,跪求!
????? 傳輸對象模式我想具體的實例代碼我就簡單的書寫下吧,就是把對象中的行為去掉,只包含數(shù)據(jù)信息,就和我們平時說的3層結(jié)構(gòu)中的Model層一樣,只有g(shù)et;set;
訪問器和私有成員變量,我們來看看實例代碼吧?
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | /// <summary> /// 產(chǎn)品信息 /// </summary> public?class?Product { ?????private?int?_pro_id; ?????private?string?_pro_property = string.Empty; ?????private?string?_pro_cid; ?????private?int? _pro_brandid; ?????private?string?_pro_name; ?????private?string?_pro_model; ?????/// <summary> ?????/// 產(chǎn)品ID ?????/// </summary> ?????public?int?pro_ID ?????{ ?????????set ?????????{ ?????????????_pro_id = value; ?????????} ?????????get ?????????{ ?????????????return?_pro_id; ?????????} ?????} ?????/// <summary> ?????/// 擴展屬性值 ?????/// </summary> ?????public?string?pro_Property ?????{ ?????????set ?????????{ ?????????????_pro_property = value; ?????????} ?????????get ?????????{ ?????????????return?_pro_property; ?????????} ?????} ?????/// <summary> ?????/// 商品分類 ?????/// </summary> ?????public?string?pro_CID ?????{ ?????????set ?????????{ ?????????????_pro_cid = value; ?????????} ?????????get ?????????{ ?????????????return?_pro_cid; ?????????} ?????} ?????/// <summary> ?????/// 商品品牌 ?????/// </summary> ?????public?int? pro_BrandID ?????{ ?????????set ?????????{ ?????????????_pro_brandid = value; ?????????} ?????????get ?????????{ ?????????????return?_pro_brandid; ?????????} ?????} ?????/// <summary> ?????/// 商品名稱 ?????/// </summary> ?????public?string?pro_Name ?????{ ?????????set ?????????{ ?????????????_pro_name = value; ?????????} ?????????get ?????????{ ?????????????return?_pro_name; ?????????} ?????} ?????/// <summary> ?????/// 商品型號 ?????/// </summary> ?????public?string?pro_Model ?????{ ?????????set ?????????{ ?????????????_pro_model = value; ?????????} ?????????get ?????????{ ?????????????return?_pro_model; ?????????} ?????} } |
?????? 我這里提供一個我認為的生成領(lǐng)域模型的思路,主要還是通過XML文件來完成,將具體的數(shù)據(jù)傳輸對象不是通過類文件的形式來完成,通過序列化成XML文件來完
成,這樣就相當于每個XML對應(yīng)一個序列化文件,然后這個文件中會保存相應(yīng)的配置信息,比如說哪個頁面顯示哪些字段,那個頁面調(diào)用這個類時不掉用這個頁面。具
體的配置通過提供一個可視化的方式來維護就好了,然后在前臺綁定的時候根據(jù)讀取或者寫入XML文件來完成,可能這也是比較靈活的方式,具體的實現(xiàn)我沒有去做,
請大家提出更好的思路,小弟謝過!
?????? 我們接下來講述第三種模式:適配器模式,這個也是設(shè)計模式中最常用的設(shè)計模式的一種,適配器模式的主要作用是將某個接口轉(zhuǎn)換成我們需要的另外一個接口,
這個怎么理解呢?
????????我們把手機服務(wù)包裝成MP3的接口,或者把MP3的接口包裝成手機,都是可以的,可能我這里的例子舉得不合適
?????? 但是意思就是將某種服務(wù),通過適配器轉(zhuǎn)換成另外一種服務(wù)。
?????? 我這里簡單的講解幾個例子來完整適配器模式的介紹,我們先以將傳輸對象轉(zhuǎn)換為我們的領(lǐng)域模型中的對象,通過適配器來完成數(shù)據(jù)的轉(zhuǎn)換。
?????? 我們先來看看不通過適配器模式來完成領(lǐng)域?qū)ο笾械念惻c傳輸對象之間的交互,通過構(gòu)造函數(shù)注入的方式來完成。
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | /// <summary> /// 產(chǎn)品信息 /// </summary> public?class?ProductCase { ????private?Product _product; ????public?ProductCase(Product product) ????{ ????????_product = product; ????} ????/// <summary> ????/// 產(chǎn)品ID ????/// </summary> ????public?int?pro_ID ????{ ????????set ????????{ ????????????_product.pro_ID = value; ????????} ????????get ????????{ ????????????return?_product.pro_ID; ????????} ????} ????/// <summary> ????/// 擴展屬性值 ????/// </summary> ????public?string?pro_Property ????{ ????????set ????????{ ????????????_product.pro_Property = value; ????????} ????????get ????????{ ????????????return?_product.pro_Property; ????????} ????} ????/// <summary> ????/// 商品分類 ????/// </summary> ????public?string?pro_CID ????{ ????????set ????????{ ????????????_product.pro_CID = value; ????????} ????????get ????????{ ????????????return?_product.pro_CID; ????????} ????} ????/// <summary> ????/// 商品品牌 ????/// </summary> ????public?int? pro_BrandID ????{ ????????set ????????{ ????????????_product.pro_BrandID = value; ????????} ????????get ????????{ ????????????return?_product.pro_BrandID; ????????} ????} ????/// <summary> ????/// 商品名稱 ????/// </summary> ????public?string?pro_Name ????{ ????????set ????????{ ????????????_product.pro_Name = value; ????????} ????????get ????????{ ????????????return?_product.pro_Name; ????????} ????} ????/// <summary> ????/// 商品型號 ????/// </summary> ????public?string?pro_Model ????{ ????????set ????????{ ????????????_product.pro_Model = value; ????????} ????????get ????????{ ????????????return?_product.pro_Model; ????????} ????} } |
????? 上面的方式通過構(gòu)造函數(shù)的注入完成相應(yīng)的訪問,通過get;set;訪問器來完成。
????? 下面我們通過適配器的方式來實現(xiàn)轉(zhuǎn)換,看看有什么不同:
?| 1 2 3 4 5 6 7 8 9 | public?class?ProductTest? { ????private?Product _product; ????public?ProductTest(Product product) ????{ ????????ProductAdapter adapter = new?ProductAdapter(product); ????????adapter.InitDTO(this); ????} } |
?????? 下面看看具體的適配器中的代碼:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public?class?ProductAdapter { ????private?Product _product; ????public?ProductAdapter(Product product) ????{ ????????this._product = product; ????} ????public?bool?InitDTO(ProductTest test) ????{ ????????//賦值的過程,將Product中的信息轉(zhuǎn)換為ProductTest對象 ????????test.pro_BrandID = _product.pro_BrandID; ????????//... ????????return?true; ????} } |
?????? 我們上面看到了,通過依賴注入的形式,將要包裝的接口傳入到適配器,然后在適配器的內(nèi)部進行相應(yīng)的包裝,傳出包裝后的接口,這就是一個完整的適配器流
程,具體的業(yè)務(wù)邏輯就是根據(jù)需要來做了。通過上面的方式我們的確完成了相應(yīng)的轉(zhuǎn)換,不過轉(zhuǎn)換的代價是非常的大,不過有的時候我們的業(yè)務(wù)需求是這樣的,可能我
們也沒有更好的辦法,只能通過這樣的方式來做,可能對解決方案的實現(xiàn)比效率更有價值。其實我們在使用傳輸對象的時候還是需要仔細的斟酌項目的需求,看看是不
是必須要使用這個,如果不是必須的,其實我們可以不需要強迫性的使用。
六、本文總結(jié)
??????? 本章主要講述了系統(tǒng)架構(gòu)中的服務(wù)層的架構(gòu)中的注意事項及幾個簡單的設(shè)計模式及使用,并且講述了服務(wù)層應(yīng)用的場景和帶來的好處,當然我們也需要服務(wù)層的
優(yōu)劣處,還有就是服務(wù)的實現(xiàn)方案,本文前面可能沒有講解發(fā)布服務(wù)的幾種方式,這里簡單的用圖來說明下吧?
?????????WCF已經(jīng)內(nèi)置繼承了remoting,socket和SOAP的方式來進行遠程調(diào)用服務(wù),當然HTTP方式的SOAP的服務(wù)方
式,還是推薦使用Web服務(wù)的方式來做。
轉(zhuǎn)載于:https://www.cnblogs.com/ywsoftware/archive/2013/01/31/2887138.html
總結(jié)
以上是生活随笔為你收集整理的系统架构师-基础到企业应用架构-服务层的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对象使用的两种方法
- 下一篇: windows phone 8 的新特性