模板方法模式實踐

2021-09-20 08:08:58 字數 3834 閱讀 2975

在實際程式設計中,會經常遇到多個類中的某些方法實現邏輯類似的情況,這時我們可以將這些類中的相同部分抽象到父類中,對於有差異的地方,子類根據自身的實際需求來各自實現。

以羽毛球運動為例,打球必有發接髮環節,發球分正手和反手兩種(這裡不談論羽球技術細節),一般男單反手發球,女單正手發球,但發接髮這個環節的流程是一致的。

}程式開發中有個重要的原則:don't repeat yourself。而上面一段**中,子類mensinglewomensingle中的play方法是重複的,羽毛球運動除男單、女單外還有男雙,女雙,混雙,如此則**中至少五處重複,這顯然不利於日後維護。

接下來對**進行改進:

abstract

class

badminton

}class

mensingle : badminton

protected

override

void

catch()

}class

womensingle : badminton

protected

override

void

catch()

}

這段**將play方法放到父類中實現,對於有差異的servecatch則交有子類實現,這邊是模板方法模式,封裝不變部分,擴充套件可變部分。其中play方法稱之為模板方法,servecatch稱為基本方法。

通常模板方法(可以有多個)在父類中實現並呼叫基本方法以完成固定的邏輯,且不允許子類重寫。

基本方法一般為抽象方法,由子類來完成具體的實現。基本方法的訪問修飾符通常是protected,不需要對外界暴露(迪公尺特法則),客戶端只需要呼叫模板方法即可。

那麼,問題來了,世界羽聯沒有規定男單必須用反手發球,女單必須正手發球。如果男單想用正手發球怎麼辦?為適應這種有著多種可能的場景,我們對**稍作調整:

abstract

class

badminton

private

void

backhandserve()

protected

abstract

void

catch();

protected

abstract

bool isforehandserve

public

void

play()

else

catch();

}}class

mensingle : badminton

}class

womensingle : badminton

}

這裡,我們通過在子類中實現屬性isforehandserve來控制父類中具體呼叫forehandserve方法還是呼叫backhandserve方法。屬性isforehandserve稱為鉤子函式,根據鉤子函式的不同實現,模板方法可以有不同的執行結果,即子類對父類產生了影響。

以上,是乙個模板方法的杜撰使用場景。模板方法模式有個很重要的特徵:父類控制流程,子類負責具體細節的實現。這裡有沒有聯想到ioc(控制反轉)?ioc的實現方式有多種,di只是其中之一,模板方法模式也可以。

許多框架(如:asp.net mvc)也是這個套路,框架定義一套流程,然後由不同的類負責不同功能的實現,並預留擴充套件點讓開發人員可根據實際需求進行擴充套件開發,但整個框架的處理流程開發人員是控制不了的。

模板方法模式有以下優點:

1、封裝不變部分,擴充套件可變部分;

寫程式就因該是這樣,不僅僅是在模板方法模式中

2、提取公共部分便於日後維護;

ctrl + c,ctrl + v **好,但濫用也是要命的

3、父類控制流程,子類負責實現;

如此,子類便可通過擴充套件的方式來增加功能;

同時,對於一些複雜的演算法,我們可以現在父類的模板方法中定義好流程,然後再在子類中去實現,思路上也會清晰不少;

最後,附一段使用模板方法模式寫的分頁查詢**:

public

class

dbbase

不得為空!");}}

protected

virtual

string

connectionstring

}protected

sqlconnection createsqlconnection()

protected sqlconnection createsqlconnection(string

connnectionstring)

return

dbconnection;

}

public

inte***ce ipagingquerywhere t : class

//////

分頁查詢

/// ///

頁碼 ///

每頁資料量

///ienumerablepagingquery(int pagenumber, int

pagesize);

}

public

abstract

class pagingquerydalbase: dbbase, ipagingquerywhere t : class

return

datacount;

}//////

分頁查詢sql

/// protected

abstract

string pagingquerysql(int pagenumber, int

pagesize);

public ienumerablepagingquery(int pagenumber, int

pagesize)

if (pagesize <= 0

)

ienumerable

result;

using (sqlconnection sqlconnection =createsqlconnection())

return

result;}}

模板方法模式實踐小結

模板方法模式用於固定演算法的骨架,讓具體演算法在子類中擴充套件,類圖如下 最顯著的特點是模板方法templatemethod 已經不需要在子類中覆蓋 head first設計模式這本書中對這個演算法有深入分析,可以參考 接下去要講的是專案中對這個模式的應用.首先有個productchecker的父類...

模板方法模式

有這樣乙個場景 乙個演算法或流程,它的步驟以及步驟之間的順序是固定的,但具體的某一步可能有不同的實現。對於這麼乙個場景,可以建立多個類,各個類實現不同的實現,但是這樣的缺點是 易錯 難改,易錯 應為步驟和順序是固定的,而且在每個類中都要寫一遍,程式設計師怎有心情不好的時候,就有可能把其中某一步給寫錯...

模板方法模式

模板方法模式 定義乙個演算法框架,將裡面的操作步驟推遲到子類中去執行,這樣使得子類不用改變框架,只需改變某些操作步驟方法 ifndef test h define test h include include using namespace std class test virtual test v...