一次重構(gòu)導(dǎo)向設(shè)計(jì)模式的實(shí)踐(.NET)
2024-07-10 12:59:37
供稿:網(wǎng)友
 
本文來源于網(wǎng)頁設(shè)計(jì)愛好者web開發(fā)社區(qū)http://www.html.org.cn收集整理,歡迎訪問。代碼僅僅是說明問題,和實(shí)際的有所不同
在項(xiàng)目開發(fā)過程中,有這樣的需求:定義一個(gè)查詢窗體使用datagrid顯示列表
雙擊grid后打開指定記錄的編輯頁面,窗體類為formsearchentity于是這么寫了
private void grid_doubleclick(object sender,system.eventargs e)
{
 string entityid = 雙擊記錄的id字段值; //這個(gè)有固定的辦法
 formentity frmentity = new formentity(entityid);
 ........
 frmentity.show();
}
其中的formentity就是對(duì)業(yè)務(wù)實(shí)體的編輯界面,在構(gòu)造函數(shù)中傳入一個(gè)id,然后
加載該記錄的相關(guān)數(shù)據(jù),在這里不作重點(diǎn)解釋。
接下來有要在查詢界面上添加一個(gè)按鈕“go”,執(zhí)行的動(dòng)作和grid雙擊是一樣的,就是
在grid中選中記錄,點(diǎn)擊go打開實(shí)體的操作界面。
這樣,就使用重構(gòu)中的extract method手法:
private void grid_doubleclick(object sender,system.eventargs e)
{
 string entityid = 雙擊記錄的id字段值;
 openentityform(entityid);
 
}
private void btngo_click(object sender,system.eventargs e )
{
 string entityid = 雙擊記錄的id字段值;
 openentityform(entityid);
}
private void openentityform(string entityid)
{
 formentity frmentity = new formentity(entityid);
 ........
 frmentity.show();
}
到現(xiàn)在看來,這樣作有什么用呢?直接在go的click時(shí)間中調(diào)用grid的doubleclick不就行了嗎?事實(shí)上extract method不僅僅是防止重復(fù)代碼
同時(shí)也可以提高代碼的可重用性,作用在下面會(huì)看到。
現(xiàn)在,又要對(duì)另一個(gè)的表進(jìn)行同樣的操作,那就再定義一個(gè)窗體,把上面的代碼改改就成了,但是就出現(xiàn)了重復(fù)代碼,這是不好的味道。那么這樣作:把openentityform方法改為virtual,同時(shí)聲明為protected,里面的代碼都去掉
protected void openentityform(string entityid)
{
 
}
把窗體更名為formsearchentitybase再重新寫一個(gè)類formsearchentitya來繼承formsearchentitybase,override父類的openentityform方法
protected override void openentityform(string entityid)
{
 formentitya frmentitya = new formentitya(entityid);
 ........
 frmentitya.show();
}
實(shí)體b的查詢界面也一樣formsearchentityb繼承自formsearchentitybase,override父類的openentityform方法
protected override void openentityform(string entityid)
{
 formentityb frmentityb = new formentityb(entityid);
 ........
 frmentityb.show();
}
這樣,如果后面還有相同的需求,就從formsearchentitybase繼承一個(gè)類,override父類的openentityform方法就可以了
現(xiàn)在,來看看templatemethod模式
意圖:
 定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。
適用性:
 一次性實(shí)現(xiàn)一個(gè)算法的不變的部分,并將可變的行為留給子類來實(shí)現(xiàn)。 
各子類中公共的行為應(yīng)被提取出來并集中到一個(gè)公共父類中以避免代碼重復(fù)
控制子類擴(kuò)展
例子代碼:
namespace templatemethod_designpattern
{
 using system;
 class algorithm 
 {
 public void doalgorithm() 
 {
 console.writeline("in doalgorithm");
 
 // do some part of the algorithm here
 
 // step1 goes here
 console.writeline("in algorithm - doalgostep1"); 
 // . . . 
 // step 2 goes here
 console.writeline("in algorithm - doalgostep2"); 
 // . . . 
 // now call configurable/replacable part
 doalgostep3();
 // step 4 goes here
 console.writeline("in algorithm - doalgostep4"); 
 // . . . 
 // now call next configurable part
 doalgostep5();
 }
 virtual public void doalgostep3()
 {
 console.writeline("in algorithm - doalgostep3"); 
 }
 virtual public void doalgostep5()
 {
 console.writeline("in algorithm - doalgostep5"); 
 }
 }
 class customalgorithm : algorithm
 {
 public override void doalgostep3()
 {
 console.writeline("in customalgorithm - doalgostep3");
 }
 public override void doalgostep5()
 {
 console.writeline("in customalgorithm - doalgostep5");
 }
 }
 /// <summary>
 /// summary description for client.
 /// </summary>
 public class client
 {
 public static int main(string[] args)
 {
 customalgorithm c = new customalgorithm();
 c.doalgorithm();
 return 0;
 }
 }
}
再來對(duì)比下上面對(duì)窗體類進(jìn)行改動(dòng)的代碼和templatemethod的例子代碼,這就是一個(gè)templatemethod模式了
有一種觀點(diǎn)說在設(shè)計(jì)期使用設(shè)計(jì)模式常會(huì)導(dǎo)致過渡設(shè)計(jì),目前的敏捷方法和重構(gòu)都漸漸提倡代碼演化和重構(gòu)達(dá)到設(shè)計(jì)模式。
我也是在寫完代碼后才發(fā)現(xiàn)這已經(jīng)是一個(gè)模式了。