Design Pattern : Template
1.
What is Template
記得小時候,寒假開始前,老師一定會叫我們過完寒假要寫一篇出遊的作文。
然而過完寒假後,一定是沒有寫 XD
這時候我們幾個死黨就會去找班上功課最好的同學A,準備把他的作文拿來抄一抄。
A:「你們大家全部抄我的,一模一樣一定會被老師發現。」
於是A拿起他的作文,在以下的地方改成空格,要我們自行填入:
作文題目:寒假出遊
我今天去___,看到很多___,中午和家人一起吃___。
沒錯! 這個就是我們最早使用的Template!
也就是只要先寫好父類別的方法,(寒假出遊)
這個方法裡面呼叫了自己的一些abstract方法以及決定執行順序。(我今天去、看到很多 …)
接著只要定義一些子類別繼承父類別,再來override這些abstract方法即可。
例如 我就可以把這篇作文寫成:
我今天去動物園,看到很多動物,中午和家人一起吃肯德基。
記得小時候,寒假開始前,老師一定會叫我們過完寒假要寫一篇出遊的作文。
然而過完寒假後,一定是沒有寫 XD
這時候我們幾個死黨就會去找班上功課最好的同學A,準備把他的作文拿來抄一抄。
A:「你們大家全部抄我的,一模一樣一定會被老師發現。」
於是A拿起他的作文,在以下的地方改成空格,要我們自行填入:
作文題目:寒假出遊
我今天去___,看到很多___,中午和家人一起吃___。
沒錯! 這個就是我們最早使用的Template!
也就是只要先寫好父類別的方法,(寒假出遊)
這個方法裡面呼叫了自己的一些abstract方法以及決定執行順序。(我今天去、看到很多 …)
接著只要定義一些子類別繼承父類別,再來override這些abstract方法即可。
例如 我就可以把這篇作文寫成:
我今天去動物園,看到很多動物,中午和家人一起吃肯德基。
u 定義好method的內容,當作範本,讓其他程式使用。
u 透過繼承的方式,讓子類別能夠實作不同的邏輯區塊。
u 在父類別的method中,依相同順序執行不同區塊的邏輯。
u 所以不同的子類別,能夠實作各自的方法細節,然後統一利用父類別的final method,來執行任務
3.
An Example
實務上,常常對後端資料庫做查詢,如果有多種資料庫(如MS sql Server, Oracle…),查詢的流程其實一樣,只是細節可能不同(如資料庫連線設定,開啟關閉連線…etc)
所以我們利用Template來實作資料庫查詢的類別。
實務上,常常對後端資料庫做查詢,如果有多種資料庫(如MS sql Server, Oracle…),查詢的流程其實一樣,只是細節可能不同(如資料庫連線設定,開啟關閉連線…etc)
所以我們利用Template來實作資料庫查詢的類別。
u 定義父類別 ConnModel:
備註1. DoQuery 就是決定查詢的步驟的方法。
備註2.可以使用mark掉的那些程式碼,由宣告的子類別來進一步控制父類別的方法。 例如:子類別不須要關閉連線這個步驟,則將isCloseConn這個標記設定為false即可。
備註1. DoQuery 就是決定查詢的步驟的方法。
備註2.可以使用mark掉的那些程式碼,由宣告的子類別來進一步控制父類別的方法。 例如:子類別不須要關閉連線這個步驟,則將isCloseConn這個標記設定為false即可。
public abstract
class ConnModel
{
private SqlConnection sqlConn; //資料庫物件
protected
abstract void
Setup(); //做資料庫連線設定
protected
abstract void
StartConn(); //開始連線
protected
abstract DataTable
Query(String sSql); //查詢
protected
abstract void
EndConn(); //關閉連線
//public bool
isCloseConn = true; //是否關閉連線 (預設:是)
/// <summary>
/// 查詢
/// </summary>
///<param
name="sSql">SQL指令</param>
public DataTable DoQuery(String
sSql)
{
try
{
Setup();
StartConn();
return
Query(sSql);
}
catch
(Exception ex)
{
throw
ex;
}
finally
{
//if
(isCloseConn == true) //檢查是否自動關閉連線
//{
EndConn();
//}
}
}
}
u 定義第一個MS Sql Server子類別 :MSSql
這邊可以很清楚看到,這個子類別只是將繼承的ConnModel裡面的abstract方法override成自己的內容。
這邊可以很清楚看到,這個子類別只是將繼承的ConnModel裡面的abstract方法override成自己的內容。
public class
MSSql : ConnModel
{
/// <summary>
/// 開始連線
/// </summary>
protected
override void
StartConn()
{
Console.WriteLine("建立MS Sql Server連線!");
}
/// <summary>
/// 做資料庫連線設定
/// </summary>
protected
override void
Setup()
{
Console.WriteLine("資料庫連線設定!");
}
/// <summary>
/// 查詢
/// </summary>
/// <param
name="sSql"></param>
/// <returns></returns>
protected
override DataTable
Query(String sSql)
{
Console.WriteLine("開始查詢MS Sql Server後端資料庫!");
return
null;
}
/// <summary>
/// 關閉連線
/// </summary>
protected
override void
EndConn()
{
Console.WriteLine("關閉MS Sql Server資料庫連線!");
}
}
}
u 定義第二個Oracle子類別 :Oracle
就不列出程式碼了,只是把上面輸出的部分稍微修改。
就不列出程式碼了,只是把上面輸出的部分稍微修改。
u 主程式(mark掉的部分,就是備註2.提到的東西)
Oracle _oracle = new Oracle();
String sSql_oracle = "SELECT 1 FROM DUAL";
//_oracle.isCloseConn = true;
_oracle.DoQuery(sSql_oracle);
_oracle = null;
MSSql _mssql = new MSSql();
String sSql_ms = "SELECT 1 ";
//_mssql.isCloseConn = false;
_mssql.DoQuery(sSql_ms);
_mssql = null;
Oracle _oracle = new Oracle();
String sSql_oracle = "SELECT 1 FROM DUAL";
//_oracle.isCloseConn = true;
_oracle.DoQuery(sSql_oracle);
_oracle = null;
MSSql _mssql = new MSSql();
String sSql_ms = "SELECT 1 ";
//_mssql.isCloseConn = false;
_mssql.DoQuery(sSql_ms);
_mssql = null;
u
執行結果
資料庫連線設定!
資料庫連線設定!
建立Oracle連線!
開始查詢Oracle後端資料庫!
關閉Oracle資料庫連線!
資料庫連線設定!
建立MS Sql Server連線!
開始查詢MS Sql Server後端資料庫!
關閉MS Sql Server資料庫連線!
4.
至於優缺點,我參考書上的內容~
優點:符合OCP,易於維護。
缺點:步驟寫在父類別,但是步驟的邏輯寫在子類別,造成程式碼不易閱讀。
優點:符合OCP,易於維護。
缺點:步驟寫在父類別,但是步驟的邏輯寫在子類別,造成程式碼不易閱讀。
沒有留言:
張貼留言