亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

(第Ⅲ部分 結(jié)構(gòu)型模式篇) 第11章 外觀模式(Fa?

系統(tǒng) 2223 0
——.NET設(shè)計(jì)模式系列之十二
Terrylee 2006 3
概述
在軟件開發(fā)系統(tǒng)中,客戶程序經(jīng)常會(huì)與復(fù)雜系統(tǒng)的內(nèi)部子系統(tǒng)之間產(chǎn)生耦合,而導(dǎo)致客戶程序隨著子系統(tǒng)的變化而變化。那么如何簡(jiǎn)化客戶程序與子系統(tǒng)之間的交互接口?如何將復(fù)雜系統(tǒng)的內(nèi)部子系統(tǒng)與客戶程序之間的依賴解耦?這就是要說(shuō)的 Fa?ade 模式。

意圖
為子系統(tǒng)中的一組接口提供一個(gè)一致的界面, Facade 模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。 [GOF 《設(shè)計(jì)模式》 ]

示意圖
門面模式?jīng)]有一個(gè)一般化的類圖描述,下面是一個(gè)示意性的對(duì)象圖:
1 Fa?ade 模式示意性對(duì)象圖
生活中的例子
外觀模式為子系統(tǒng)中的接口定義了一個(gè)統(tǒng)一的更高層次的界面,以便于使用。當(dāng)消費(fèi)者按照目錄采購(gòu)時(shí),則體現(xiàn)了一個(gè)外觀模式。消費(fèi)者撥打一個(gè)號(hào)碼與客服代表聯(lián)系,客服代表則扮演了這個(gè) " 外觀 " ,他包含了與訂貨部、收銀部和送貨部的接口。
2 使用電話訂貨例子的外觀模式對(duì)象圖
Facade 模式解說(shuō)
我們平時(shí)的開發(fā)中其實(shí)已經(jīng)不知不覺(jué)的在用 Fa?ade 模式,現(xiàn)在來(lái)考慮這樣一個(gè)抵押系統(tǒng),當(dāng)有一個(gè)客戶來(lái)時(shí),有如下幾件事情需要確認(rèn):到銀行子系統(tǒng)查詢他是否有足夠多的存款,到信用子系統(tǒng)查詢他是否有良好的信用,到貸款子系統(tǒng)查詢他有無(wú)貸款劣跡。只有這三個(gè)子系統(tǒng)都通過(guò)時(shí)才可進(jìn)行抵押。我們先不考慮 Fa?ade 模式,那么客戶程序就要直接訪問(wèn)這些子系統(tǒng),分別進(jìn)行判斷。類結(jié)構(gòu)圖下:
3
在這個(gè)程序中,我們首先要有一個(gè)顧客類,它是一個(gè)純數(shù)據(jù)類,并無(wú)任何操作,示意代碼:

// 顧客類
public class Customer
{
private string _name;

public Customer( string name)
{
this ._name = name;
}


public string Name
{
get { return _name;}
}

}

下面這三個(gè)類均是子系統(tǒng)類,示意代碼:
// 銀行子系統(tǒng)
public class Bank
{
public bool HasSufficientSavings(Customerc, int amount)
{
Console.WriteLine(
" Checkbankfor " + c.Name);
return true ;
}

}


// 信用子系統(tǒng)
public class Credit
{
public bool HasGoodCredit(Customerc)
{
Console.WriteLine(
" Checkcreditfor " + c.Name);
return true ;
}

}


// 貸款子系統(tǒng)
public class Loan
{
public bool HasNoBadLoans(Customerc)
{
Console.WriteLine(
" Checkloansfor " + c.Name);
return true ;
}

}

來(lái)看客戶程序的調(diào)用:

Fa?ade 模式的情況下,客戶程序與三個(gè)子系統(tǒng)都發(fā)生了耦合,這種耦合使得客戶程序依賴于子系統(tǒng),當(dāng)子系統(tǒng)變化時(shí),客戶程序也將面臨很多變化的挑戰(zhàn)。一個(gè)合情合理的設(shè)計(jì)就是為這些子系統(tǒng)創(chuàng)建一個(gè)統(tǒng)一的接口,這個(gè)接口簡(jiǎn)化了客戶程序的判斷操作。看一下引入 Fa?ade 模式后的類結(jié)構(gòu)圖:
// 客戶程序
public class MainApp
{
private const int _amount = 12000 ;

public static void Main()
{
Bankbank
= new Bank();
Loanloan
= new Loan();
Creditcredit
= new Credit();

Customercustomer
= new Customer( " AnnMcKinsey " );

bool eligible = true ;

if ( ! bank.HasSufficientSavings(customer,_amount))
{
eligible
= false ;
}

else if ( ! loan.HasNoBadLoans(customer))
{
eligible
= false ;
}

else if ( ! credit.HasGoodCredit(customer))
{
eligible
= false ;
}


Console.WriteLine(
" /n " + customer.Name + " hasbeen " + (eligible ? " Approved " : " Rejected " ));
Console.ReadLine();
}

}

可以看到,在不用
4
門面類 Mortage 的實(shí)現(xiàn)如下:
// 外觀類
public class Mortgage
{
private Bankbank = new Bank();
private Loanloan = new Loan();
private Creditcredit = new Credit();

public bool IsEligible(Customercust, int amount)
{
Console.WriteLine(
" {0}appliesfor{1:C}loan/n " ,
cust.Name,amount);

bool eligible = true ;

if ( ! bank.HasSufficientSavings(cust,amount))
{
eligible
= false ;
}

else if ( ! loan.HasNoBadLoans(cust))
{
eligible
= false ;
}

else if ( ! credit.HasGoodCredit(cust))
{
eligible
= false ;
}


return eligible;
}

}

顧客類和子系統(tǒng)類的實(shí)現(xiàn)仍然如下:
// 銀行子系統(tǒng)
public class Bank
{
public bool HasSufficientSavings(Customerc, int amount)
{
Console.WriteLine(
" Checkbankfor " + c.Name);
return true ;
}

}


// 信用證子系統(tǒng)
public class Credit
{
public bool HasGoodCredit(Customerc)
{
Console.WriteLine(
" Checkcreditfor " + c.Name);
return true ;
}

}


// 貸款子系統(tǒng)
public class Loan
{
public bool HasNoBadLoans(Customerc)
{
Console.WriteLine(
" Checkloansfor " + c.Name);
return true ;
}

}


// 顧客類
public class Customer
{
private string name;

public Customer( string name)
{
this .name = name;
}


public string Name
{
get { return name;}
}

}

而此時(shí)客戶程序的實(shí)現(xiàn):
Fa?ade 模式后,客戶程序只與 Mortgage 發(fā)生依賴,也就是 Mortgage 屏蔽了子系統(tǒng)之間的復(fù)雜的操作,達(dá)到了解耦內(nèi)部子系統(tǒng)與客戶程序之間的依賴。

// 客戶程序類
public class MainApp
{
public static void Main()
{
// 外觀
Mortgagemortgage = new Mortgage();

Customercustomer
= new Customer( " AnnMcKinsey " );
bool eligable = mortgage.IsEligible(customer, 125000 );

Console.WriteLine(
" /n " + customer.Name +
" hasbeen " + (eligable ? " Approved " : " Rejected " ));
Console.ReadLine();
}

}

可以看到引入
.NET 架構(gòu)中的 Fa?ade 模式
Fa?ade 模式在實(shí)際開發(fā)中最多的運(yùn)用當(dāng)屬開發(fā) N 層架構(gòu)的應(yīng)用程序了,一個(gè)典型的 N 層結(jié)構(gòu)如下:
5
在這個(gè)架構(gòu)中,總共分為四個(gè)邏輯層,分別為:用戶層 UI ,業(yè)務(wù)外觀層 Business Fa?ade ,業(yè)務(wù)規(guī)則層 Business Rule ,數(shù)據(jù)訪問(wèn)層 Data Access 。其中 Business Fa?ade 層的職責(zé)如下:
l 從“用戶”層接收用戶輸入
l 如果請(qǐng)求需要對(duì)數(shù)據(jù)進(jìn)行只讀訪問(wèn),則可能使用“數(shù)據(jù)訪問(wèn)”層
l 將請(qǐng)求傳遞到“業(yè)務(wù)規(guī)則”層
l 將響應(yīng)從“業(yè)務(wù)規(guī)則”層返回到“用戶”層
l 在對(duì)“業(yè)務(wù)規(guī)則”層的調(diào)用之間維護(hù)臨時(shí)狀態(tài)
對(duì)這一架構(gòu)最好的體現(xiàn)就是 Duwamish 示例了。在該應(yīng)用程序中,有部分操作只是簡(jiǎn)單的從數(shù)據(jù)庫(kù)根據(jù)條件提取數(shù)據(jù),不需要經(jīng)過(guò)任何處理,而直接將數(shù)據(jù)顯示到網(wǎng)頁(yè)上,比如查詢某類別的圖書列表。而另外一些操作,比如計(jì)算定單中圖書的總價(jià)并根據(jù)顧客的級(jí)別計(jì)算回扣等等,這部分往往有許多不同的功能的類,操作起來(lái)也比較復(fù)雜。如果采用傳統(tǒng)的三層結(jié)構(gòu),這些商業(yè)邏輯一般是會(huì)放在中間層,那么對(duì)內(nèi)部的這些大量種類繁多,使用方法也各異的不同的類的調(diào)用任務(wù),就完全落到了表示層。這樣勢(shì)必會(huì)增加表示層的代碼量,將表示層的任務(wù)復(fù)雜化,和表示層只負(fù)責(zé)接受用戶的輸入并返回結(jié)果的任務(wù)不太相稱,并增加了層與層之間的耦合程度。于是就引入了一個(gè) Fa?ade 層,讓這個(gè) Facade 來(lái)負(fù)責(zé)管理系統(tǒng)內(nèi)部類的調(diào)用,并為表示層提供了一個(gè)單一 而簡(jiǎn)單的接口。看一下Duwamish結(jié)構(gòu)圖:
圖6
從圖中可以看到,UI層 將請(qǐng)求發(fā)送給業(yè)務(wù)外觀層,業(yè)務(wù)外觀層對(duì)請(qǐng)求進(jìn)行初步的處理,判斷是否需要調(diào)用業(yè)務(wù)規(guī)則層,還是直接調(diào)用數(shù)據(jù)訪問(wèn)層獲取數(shù)據(jù)。最后由數(shù)據(jù)訪問(wèn)層訪問(wèn)數(shù)據(jù)庫(kù)并按 照來(lái)時(shí)的步驟返回結(jié)果到 UI 層,來(lái)看具體的代碼實(shí)現(xiàn)。
在獲取商品目錄的時(shí)候, Web UI 調(diào)用業(yè)務(wù)外觀層:

productSystem = new ProductSystem();
categorySet
= productSystem.GetCategories(categoryID);

業(yè)務(wù)外觀層直接調(diào)用了數(shù)據(jù)訪問(wèn)層:
public CategoryDataGetCategories( int categoryId)
{
//
// Checkpreconditions
//
ApplicationAssert.CheckCondition(categoryId >= 0 , " InvalidCategoryId " ,ApplicationAssert.LineNumber);
//
// Retrievethedata
//
using (CategoriesaccessCategories = new Categories())
{
return accessCategories.GetCategories(categoryId);
}


}

在添加訂單時(shí),UI調(diào)用業(yè)務(wù)外觀層:

public void AddOrder()
{
ApplicationAssert.CheckCondition(cartOrderData
!= null , " Orderrequiresdata " ,ApplicationAssert.LineNumber);

// Writetracelog.
ApplicationLog.WriteTrace( " Duwamish7.Web.Cart.AddOrder:/r/nCustomerId: " +
cartOrderData.Tables[OrderData.CUSTOMER_TABLE].Rows[
0 ][OrderData.PKID_FIELD].ToString());
cartOrderData
= ( new OrderSystem()).AddOrder(cartOrderData);
}

業(yè)務(wù)外觀層調(diào)用業(yè)務(wù)規(guī)則層:
public OrderDataAddOrder(OrderDataorder)
{
//
// Checkpreconditions
//
ApplicationAssert.CheckCondition(order != null , " Orderisrequired " ,ApplicationAssert.LineNumber);

(
new BusinessRules.Order()).InsertOrder(order);
return order;
}

業(yè)務(wù)規(guī)則層進(jìn)行復(fù)雜的邏輯處理后,再調(diào)用數(shù)據(jù)訪問(wèn)層:
public bool InsertOrder(OrderDataorder)
{
//
// Assumeit'sgood
//
bool isValid = true ;
//
// Validateordersummary
//
DataRowsummaryRow = order.Tables[OrderData.ORDER_SUMMARY_TABLE].Rows[ 0 ];

summaryRow.ClearErrors();

if (CalculateShipping(order) != (Decimal)(summaryRow[OrderData.SHIPPING_HANDLING_FIELD]))
{
summaryRow.SetColumnError(OrderData.SHIPPING_HANDLING_FIELD,OrderData.INVALID_FIELD);
isValid
= false ;
}


if (CalculateTax(order) != (Decimal)(summaryRow[OrderData.TAX_FIELD]))
{
summaryRow.SetColumnError(OrderData.TAX_FIELD,OrderData.INVALID_FIELD);
isValid
= false ;
}

//
// Validateshippinginfo
//
isValid &= IsValidField(order,OrderData.SHIPPING_ADDRESS_TABLE,OrderData.SHIP_TO_NAME_FIELD, 40 );
//
// Validatepaymentinfo
//
DataRowpaymentRow = order.Tables[OrderData.PAYMENT_TABLE].Rows[ 0 ];

paymentRow.ClearErrors();

isValid
&= IsValidField(paymentRow,OrderData.CREDIT_CARD_TYPE_FIELD, 40 );
isValid
&= IsValidField(paymentRow,OrderData.CREDIT_CARD_NUMBER_FIELD, 32 );
isValid
&= IsValidField(paymentRow,OrderData.EXPIRATION_DATE_FIELD, 30 );
isValid
&= IsValidField(paymentRow,OrderData.NAME_ON_CARD_FIELD, 40 );
isValid
&= IsValidField(paymentRow,OrderData.BILLING_ADDRESS_FIELD, 255 );
//
// Validatetheorderitemsandrecalculatethesubtotal
//
DataRowCollectionitemRows = order.Tables[OrderData.ORDER_ITEMS_TABLE].Rows;

DecimalsubTotal
= 0 ;

foreach (DataRowitemRow in itemRows)
{
itemRow.ClearErrors();

subTotal
+= (Decimal)(itemRow[OrderData.EXTENDED_FIELD]);

if ((Decimal)(itemRow[OrderData.PRICE_FIELD]) <= 0 )
{
itemRow.SetColumnError(OrderData.PRICE_FIELD,OrderData.INVALID_FIELD);
isValid
= false ;
}


if (( short )(itemRow[OrderData.QUANTITY_FIELD]) <= 0 )
{
itemRow.SetColumnError(OrderData.QUANTITY_FIELD,OrderData.INVALID_FIELD);
isValid
= false ;
}

}

//
// Verifythesubtotal
//
if (subTotal != (Decimal)(summaryRow[OrderData.SUB_TOTAL_FIELD]))
{
summaryRow.SetColumnError(OrderData.SUB_TOTAL_FIELD,OrderData.INVALID_FIELD);
isValid
= false ;
}


if (isValid)
{
using (DataAccess.OrdersordersDataAccess = new DataAccess.Orders())
{
return (ordersDataAccess.InsertOrderDetail(order)) > 0 ;
}

}

else
return false ;
}
[MSDN]

效果及實(shí)現(xiàn)要點(diǎn)
1 Fa?ade 模式對(duì)客戶屏蔽了子系統(tǒng)組件,因而減少了客戶處理的對(duì)象的數(shù)目并使得子系統(tǒng)使用起來(lái)更加方便。
2 Fa?ade 模式實(shí)現(xiàn)了子系統(tǒng)與客戶之間的松耦合關(guān)系,而子系統(tǒng)內(nèi)部的功能組件往往是緊耦合的。松耦合關(guān)系使得子系統(tǒng)的組件變化不會(huì)影響到它的客戶。
3 .如果應(yīng)用需要,它并不限制它們使用子系統(tǒng)類。因此你可以在系統(tǒng)易用性與通用性之間選擇。

適用性
1 .為一個(gè)復(fù)雜子系統(tǒng)提供一個(gè)簡(jiǎn)單接口。
2 .提高子系統(tǒng)的獨(dú)立性。
3 .在層次化結(jié)構(gòu)中,可以使用 Facade 模式定義系統(tǒng)中每一層的入口。

總結(jié)
Fa?ade 模式注重的是簡(jiǎn)化接口,它更多的時(shí)候是從架構(gòu)的層次去看整個(gè)系統(tǒng),而并非單個(gè)類的層次。

參考資料
Erich Gamma 等,《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》,機(jī)械工業(yè)出版社
Robert C.Martin ,《敏捷軟件開發(fā):原則、模式與實(shí)踐》,清華大學(xué)出版社
閻宏,《 Java 與模式》,電子工業(yè)出版社
Alan Shalloway James R. Trott ,《 Design Patterns Explained 》,中國(guó)電力出版社
MSDN WebCast C# 面向?qū)ο笤O(shè)計(jì)模式縱橫談 (11) Facade 外觀模式 ( 結(jié)構(gòu)型模式 )

(第Ⅲ部分 結(jié)構(gòu)型模式篇) 第11章 外觀模式(Fa?ade Pattern)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产欧美视频综合二区 | 亚洲区精品久久一区二区三区 | 爆操大奶美女 | 久久久久国产一级毛片高清版 | 亚洲桃色视频 | 久久天天躁日日躁狠狠躁 | 日韩精品一区二三区中文 | 国内成人精品视频 | 免费观看日本特色做爰视频在线 | 国产一级黄色毛片 | 国产真实偷乱视频在线观看 | 一区二区三区四区视频在线观看 | 国产高清美女一级毛片久久 | 欧美日本一区亚洲欧美一区 | 成人在线精品视频 | 成人国产在线视频 | 亚洲成a人片在线观看精品 亚洲成a人一区二区三区 | 久操这里只有精品 | 国产精品9999久久久久 | 日韩欧美国产偷亚洲清高 | 国内精品久久久久久麻豆 | 欧美毛片免费看 | 久久国产在线观看 | 日本精品久久久中文字幕 | 亚州综合 | 偷偷狠狠的日日高清完整视频 | 中文字幕国产专区 | 亚洲欧美日韩一区超高清 | 亚洲一区在线日韩在线深爱 | 欧美亚洲中日韩中文字幕在线 | 国产3级在线观看 | 午夜免费看| 97se亚洲 | 亚洲第一免费视频 | ijzzijzz精的女人美女 | 日本一级特黄a大片在线 | 永久福利视频 | 午夜亚洲国产精品福利 | 天天干天天插天天操 | 成人毛片免费在线观看 | 久久这里只有精品久久 |