走向.NET架构设计—第五章—业务层模式,原则,实践(中篇)
走向.NET架構設計—第五章—業務層模式,原則,實踐(中篇)
前言:設計模式并不是什么很高深的東西,至少不是那么“神乎其神”。說到底,設計模式就是一些設計思想。下面我們就走進項目,看看這些項目中這些思想是如何體現的。本系列文章會在后續文章中陸陸續續的,在恰當的時候介紹一些相應的設計模式,而不是一股腦的一起上。?
本篇的議題如下:
架構模式
設計模式
設計原則
?
?
?
?
設計模式
本篇文章主要是討論的在業務層可以采用的或者常用的一些設計模式:
Factory Method
Decorator
Template Method
State
Strategy
?
Factory Method
相信很多朋友對這個模式很熟悉了,平時在項目中或多或少總能看到Factory, Provider等。確實Factory Method一種創建型的模式,它的主要目的就是隱藏對象創建的細節。也就是說,客戶程序(或者成為調用者)不用特定來什么創建某一種具體的類,也不依賴于特定的類,而且依賴接口或者抽象類,這樣就達到了解耦,專業點的說法就是“依賴倒置”,更加直白的說法就是:客戶程序可以使用很多不同的實現類,而保持代碼不變。因為在需要的時候,傳入一些信息,Factory Methods就返回接口或者抽象類的實現類。
?
???????? 很多情況下,我們一般是這樣來使用Factory Method模式的:建立一個Factory類,這個類有一個靜態的方法,這個方法返回一個抽象的類或者接口。然后,客戶程序(或者調用程序)就傳入一些信息給Factory類來,要求Factory來創建相對應,需要的具體的實現類。
?
???????? 下面我們就看看一個Factory Method的UML圖:
?
?
?
?? 在圖中,可以得出以下幾點信息:
q?Client類通過Factory類來獲取實現了IProduct的具體子類。
q?Client類依賴IProduct接口,而不是依賴具體的子類。
q?Factory類復雜創建具體的子類,向Client隱藏具體的細節。
?
??? 現在網上購物已經很流行了,在選擇支付方式的時候,一般有幾種選擇,比如:網銀支付,貨到付款支付等。對于網銀支付,又可以進一步細分為:中國銀行支付、工商銀行支付等。不同的銀行支付,最后調用的接口都不一樣,而且以后系統可能會支持更多的銀行。所以在設計支付功能的時候需要考慮到擴展性。本例將會介紹如何采用工廠方法模式來實現支付功能。
?
? 請看下圖:
?
????????
下面我們就通過代碼來講述:(大家可以一起動手) ?
???? IPayment支付方式的接口代碼如下所示:
?
public?interface?IPayment{
??????bool?Payfor(decimal?money);
}
?
支付實現者ABCPayment支付類的代碼如下所示:
?
public?class?ABCPayment:IPayment??{
????????public?bool?Payfor(decimal?money)
????????{
???????????//調用中國農業銀行提供的支付接口進行支付
????????????return?true;
????????}
???}
?????? ICBCPayment、AOCPayment的實現同理。
?????? PaymentFactory的任務就是根據傳入的條件來創建不同的具體支付者:
?
public?class?PaymentFactory{
????????public?static?IPayment?CreatePayment(string?bank)
????????{
????????????IPayment?result?=?null;
????????????switch?(bank)
????????????{
????????????????case?"ABC":
????????????????????result?=?new?ABCPayment();
????????????????????break;
????????????????case?"ICBC":
????????????????????result?=?new?ICBCPayment();
????????????????????break;
????????????}
????????????return?result;
????????}
}
?
????? 當然,可以采用更好的方式來實現PaymentFactory的CreatePayment方法,例如采用配置文件,動態加載程序集的方式。
Decorator
??????? 為了更好地理解“裝飾”的概念,我們首先拋開枯燥的闡述,來看看現在流行的網游。在網游中玩家可以給自己的賬號購買不同的裝備,而且不同的裝備其特性也不一樣,比如重量、防御能力、攻擊能力等。下面就以裝備中的鎧甲為引子來講述“裝飾”。
?????? 下面,我們就看看如何實現鎧甲的升級功能:從最初的青銅甲一步步升級到麒麟甲。
?
??????? 其中:
Knight:代表武將。
IArmour:鎧甲接口。QTArmour為青銅鎧甲,BLGJArmour為百煉鋼甲,QLArmour為麒麟甲。
??????? 每次鎧甲升級,都是通過工廠武將創建新的鎧甲子類替換原來的鎧甲。
?
????????如果以后有新的鎧甲或要對現有的鎧甲功能進行增強,可以采用繼承的方式實現。例如現在麒麟鎧甲要增加隱形功能,本著“開放關閉原則”,最容易想到的就是添加一個新的子類,從QLArmour(青銅鎧甲)繼承現有的功能,同時再加上新的功能。如果再要新加上其他功能,其步驟也與此類似,原本就想通過繼承來重用現有的代碼,現在這個目的達到了,但是最后系統中存在了很多的功能相近的類,導致類的數目急劇膨脹。
???????如果能夠在現有鎧甲上面通過不斷的改造,增加新的功能,類似于變形金剛變身那樣,使加入了新功能的青銅甲鎧甲演變成麒麟甲,成為新類型的鎧甲,那么類的數目就不會像之前那樣膨脹了。?????
?????? 網游的例子到此暫告一個段落,主要就是想讓大家了解一下“裝飾”的含義,至于如何實現,在講完下面的例子之后大家就清楚了。
要遵循“開放關閉”原則,同時又要規避使用繼承帶來的類膨脹問題,如何實現?裝飾者模式回答了這個問題。
?
?
??? 如圖,先不管圖中類名的定義,首先看看主要類的含義:
???????? (1) OnlineSitePriceDecorator代表購物站點的打折。
???????? (2) SupplierPriceDecorator代表供應商的打折。
???????? (3) PolicyPriceDecorator代表政府要求的打折。
?
??????在打折的時候,需要考慮:打折就是改變產品的價格,而很多時候,價格往往只是產品的一個屬性,例如,通常會采用decimal等數據類型。
????? 現在因為價格總是在不斷地根據打折算法的變換而變化,那么現在“價格”就成了一個變化點;另一方面,更加準確的說:打折算法是用在價格之上的,這樣才能實現對產品的打折??紤]把價格這個變化點引出去,成為一個業務實體Price,然后把打折算法都累積在這個實體上面進行,產品類Product絲毫不知道Price類是否應用了打折算法,只管引用Price獲取最后的價格。
?
public?interface?IPrice???{
????????decimal?Cost?{?get;?set;?}
???}
public?class?Product
????{
????????public?string?Name?{?get;?set;?}
????????public?IPrice?Price?{?get;?set;?}
????}
?
下面,開始添加不同打折算法的實現。
??? 首先我們來回想一下之前裝備升級的例子,我們是希望通過不斷地改造青銅甲,在原有的基礎上加上新的功能,最后達到裝備升級的目的。此時,在價格打折上面,因為同時要采用很多的打折算法,也類似于給價格不斷的“升級”:在原有的價格上不斷進行包裝。所以OnlineSitePriceDecorator購物網站推出的打折方法如下:
?
public?class?OnlineSitePriceDecorator?:?IPrice{
????????private?IPrice?price;
????????public?OnlineSitePriceDecorator(IPrice?price)
????????{
????????????this.price?=?price;
????????}
????????public?decimal?Cost
????????{
????????????get
????????????{
????????????????return?price.Cost?*?0.9M;
????????????}
????????????set
????????????{
????????????????price.Cost?=?value;
????????????}
????????}
}
?
??? 從上面的代碼中我們可以看出,拿到商品的原價后進行包裝:proce.Cost*0.9M。在經過OnlineSitePriceDecorator包裝之后把價格拋出來,進行下一個包裝:供應商打折。供應商打折的代碼如下所示:
?
public?class?SupplierPriceDecorator?:?IPrice{
????????private?IPrice?price;
????????public?SupplierPriceDecorator(IPrice?price)
????????{
????????????this.price?=?price;
????????}
????????public?decimal?Cost
????????{
????????????get
????????????{
????????????????return?price.Cost?*?0.85M;
????????????}
????????????set
????????????{
????????????????price.Cost?=?value;
????????????}
????????}
}
?
下面看看如何實現累積打折算法,代碼如下:
?
public?class?ProductService{
????????private?IProductRepository?productRepository;
????????public?ProductService(IProductRepository?productRepository)
????????{
????????????this.productRepository?=?productRepository;
????????}
????????public?List<Product>?GetProducts()
????????{
????????????var?products?=?productRepository.GetAllProduct();
????????????products.ApplyDiscount();
????????????return?products;
????????}
}
//其中ApplyDiscount為List的擴展方法,如下所示:
public?static?class?DiscountExtension
{
????????public?static?List<Product>?ApplyDiscount(this?List<Product>?products)
????????{
????????????if?(products?!=?null?&&?products.Count?>?0)
????????????{
????????????????foreach?(var?product?in?products)
????????????????{
????????????????????product.Price?=?new?OnlineSitePriceDecorator(product.Price);
????????????????????product.Price?=?new?SupplierPriceDecorator(product.Price);
????????????????????product.Price?=?new?PolicyPriceDecorator(product.Price,?0.88M);
????????????????}
??????????}
????????????return?products;
????????}
?
價格包裝的過程如圖所示。
?
以上就是本篇的內容,講述的很粗略,希望見諒,還沒有寫完,待續!J
?
轉載于:https://www.cnblogs.com/yanyangtian/archive/2010/11/19/1881383.html
總結
以上是生活随笔為你收集整理的走向.NET架构设计—第五章—业务层模式,原则,实践(中篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TP-Link TL-WR2041N V
- 下一篇: 步步高家教机如何连接电脑?