【自然框架】——頁面基類與設計模式(二) 模板模式
橋接模式的補充:(下面的一段是橋接模式裡後補充的一段,橋接模式的一個小結)
什麼是交接模式?引用《大話設計模式》裡的定義:
橋接模式(Bridge):將抽象部分和他的實現部分分離,使他們都可以獨立的變化。(P229)
不知道大家有沒有看懂這個定義,至少我是沒弄懂,呵呵。再引用一段《大話設計模式》的一段解釋:(P232)
小菜:“我覺得交接模式所說的‘將抽象部分和他的實現部分分離’,還是不好理解,我的理解就是實現系統有多個角度分類,每一種分類都有可能有變化,那麼就把這種多角度分離出來讓他們獨立變化,減少他們之間的耦合。”
這個就是作者(程傑)的理解吧,這個解釋夠白話的了,不過我還想說一下我的更加白話的理解,呵呵。大家看看對不對。
我的理解就是:有兩套或者多套獨立的“多型系統”,他們可以各自獨立的變化(繼承),互不干擾。然後選擇一套系統作為容器,在這個容器裡定義其他系統的例項或者藉口,通過這種關係(組合/聚合)把兩套或者多套系統結合起來,配合工作。組合/聚合就好像一座橋樑一樣把這些系統結合在一起,所以就叫做橋接模式了。
就好比我的這個例子裡面,頁面基類就是一套“多型系統”,他可以派生出列表頁面基類、表單頁面基類等,把頁面基類作為容器,在其內部定義資料訪問函式庫的例項,定義當前登入人資訊的例項。而資料訪問函式庫還可以自行派生出SqlClient的訪問類、OleDb的訪問類,他們是獨立的“多型系統”互不干擾。頁面基類如何變化不需要考慮資料訪問的問題,資料訪問函式庫如何變化也不用考慮有多少種頁面。這就是所謂的減少耦合吧。
=====================================================
如果我們在頁面基類裡要做一些事情,需要制定一下執行順序,而且有一些處理方法是公用的,但是有一些處理的方式又不一樣,這時候就比較適合採用模板模式了。
比如我們在頁面基類裡override 一下OnInit(EventArgs e),在這裡制定一下執行順序,然後定義幾個虛擬函式(virtual)。程式碼如下:
/// <summary> /// 提取URL裡面的引數,驗證引數 /// </summary> /// <param name="e"></param> protected override void OnInit(EventArgs e) { base.OnInit(e); //呼叫函式來設定FunctionID,不同型別的頁面就可以用不同的方式來設定FunctionID了。 SetFunctionID(); //呼叫函式來設定ButtonID。 SetButtonID(); //呼叫函式來設定DataID。 SetDataID(); //呼叫函式來設定DepartmentID(部門ID)。 SetDepartmentID(); //呼叫函式來設定ForeignID(外來鍵ID)。 SetForeignID(); if (!Page.IsPostBack) { //設定標題 SetPageTitle(); } }
SetFunctionID()的程式碼,其他程式碼略。
/// <summary>
/// 設定FunctionID。
/// </summary>
protected virtual void SetFunctionID()
{
//DataList.aspx、DataForm.aspx 頁面通過URL裡的引數設定。
//其他頁面自行設定
this.FunctionID = Request.QueryString["fid"];
#region 驗證模組ID引數是否是數字。
if (!Functions.IsInt(this.FunctionID))
{
Response.Write("模組引數不正確!");
Response.End();
}
#endregion
}
這樣子類就繼承了基類的執行順序,然後如果有不一樣的驗證方式,那麼就override一下就可以了。
這樣做的好處就是,把共用的東西放到父類,子類只需要關注不一樣的地方。同時也強制了編寫規範,基類是寫好的,大家不能隨便修改,如果有不同的需求,可以去改子類(override),不必去改基類,這樣也遵守了開放封閉原則。
同理,列表頁面基類也採用了模板模式。
在自然框架裡面列表頁面裡需要使用分頁控制元件、查詢控制元件、資料顯示控制元件、操作按鈕組這幾個控制元件,那麼給這些控制元件設定屬性值的操作,和他們之間的關聯關係就可以放在列表頁面基類裡去做。程式碼如下:
/// <summary>
/// 在 OnInit 事件裡面設定各個自定義控制元件的屬性和關聯
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
//父類裡面驗證引數是否正確
base.OnInit(e);
//驗證是否有許可權訪問。
MyUser.CheckFunctionID(this.FunctionID);
//設定分頁控制元件的屬性和事件
SetQuickPagerInfo();
//設定資料表格的屬性
SetGridInfo();
//設定查詢控制元件的屬性
SetFindControlInfo();
//設定操作按鈕的屬性
SetButtonBarInfo();
}
雖然大多數列表頁面都可以這麼設定,但是也不排除特殊需求,如果又不一樣的需求的話,那麼就可以在子類裡面通過override的方式來實現自己的特殊需求。
還是那句話,把共用的放在基類裡面,子類只關心不同點即可。
模板模式的定義: 還是引用《大話設計模式》裡的定義。
模板方法模式:定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。模版方法可以使得子類可以不修改一個演算法的結構既可以重定義該演算法的某些特定步驟。【P96】
當然我這裡說的只是模板模式的一種形式的應用,除了這種形式的用法外還有很多種形式的用法。
全部原始碼下載:http://www.cnblogs.com/jyk/archive/2009/10/28/1591680.html
=============================================
白天不能上網,被遮蔽了,所以白天就不能及時回覆了,晚上在回覆。