日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

31模板方法(Template Method)

發(fā)布時(shí)間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 31模板方法(Template Method) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

無(wú)處不在的Template Method?
??? 如果你只想掌握一種設(shè)計(jì)模式,那么它就是Template Method!
動(dòng)機(jī)(Motivate):
??? 變化 -----是軟件設(shè)計(jì)的永恒主題,如何管理變化帶來(lái)的復(fù)雜性?設(shè)計(jì)模式的藝術(shù)性和復(fù)雜度就在于如何
分析,并發(fā)現(xiàn)系統(tǒng)中的變化和穩(wěn)定點(diǎn),并使用特定的設(shè)計(jì)方法來(lái)應(yīng)對(duì)這種變化。
意圖(Intent):
????定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? -------《設(shè)計(jì)模式》GOF
結(jié)構(gòu)圖(Struct):
??? ?? ?? ?? ?? ????
適用性:
????

1.一次性實(shí)現(xiàn)一個(gè)算法的不變的部分,并將可變的行為留給子類來(lái)實(shí)現(xiàn)。

2.各子類中公共的行為應(yīng)被提取出來(lái)并集中到一個(gè)公共父類中以避免代碼重復(fù)。這是Opdyke和Johnson所描述過的“重分解以一般化”的一個(gè)很好的例子。首先識(shí)別現(xiàn)有代碼中的不同之處,并且將不同之處分離為新的操作。最后,用一個(gè)調(diào)用這些新的操作的模板方法來(lái)替換這些不同的代碼。

3.控制子類擴(kuò)展。模板方法只在特定點(diǎn)調(diào)用“Hook”操作,這樣就只允許在這些點(diǎn)進(jìn)行擴(kuò)展。
生活中的例子:
??? ?? ?? ?? ???
代碼實(shí)現(xiàn):

??? 假如我們需要簡(jiǎn)單的讀取Northwind數(shù)據(jù)庫(kù)中的表的記錄并顯示出來(lái)。對(duì)于數(shù)據(jù)庫(kù)操作,我們知道不管讀取的是哪張表,它一般都應(yīng)該經(jīng)過如下這樣的幾步:

1.連接數(shù)據(jù)庫(kù)(Connect)

2.執(zhí)行查詢命令(Select)

3.顯示數(shù)據(jù)(Display)

4.斷開數(shù)據(jù)庫(kù)連接(Disconnect)

這些步驟是固定的,但是對(duì)于每一張具體的數(shù)據(jù)表所執(zhí)行的查詢卻是不一樣的。顯然這需要一個(gè)抽象角色,給出頂級(jí)行為的實(shí)現(xiàn)。如下圖:???????????????????????????????????????????????????????????????????????????????????????????????????
?????????????????????????
Template Method模式的實(shí)現(xiàn)方法是從上到下,我們首先給出頂級(jí)框架DataAccessObject的實(shí)現(xiàn)邏輯:

?1?public?abstract?class?DataAccessObject
?2?
?3?{
?4?????protected?string?connectionString;
?5?
?6?????protected?DataSet?dataSet;
?7?
?8?????protected?virtual?void?Connect()
?9?
10?????{?
11?????????connectionString?=?
12?
13?????????????"Server=.;User?Id=sa;Password=;Database=Northwind";
14?
15?????}
16?
17????protected??abstract?void?Select();
18?
19?????protected?abstract?void?Display();
20?
21?
22?????protected?virtual?void?Disconnect()
23?
24?????{
25?????????connectionString?=?"";
26?????}
27?
28?????//?The?"Template?Method"?
29?
30?????public?void?Run()
31?
32?????{
33?????????Connect();
34?
35?????????Select();
36?
37?????????Display();
38?
39?????????Disconnect();
40?????}
41?}

顯然在這個(gè)頂級(jí)的框架DataAccessObject中給出了固定的輪廓,方法Run()便是模版方法,Template Method模式也由此而得名。而對(duì)于Select()和Display()這兩個(gè)抽象方法則留給具體的子類去實(shí)現(xiàn),如下圖:
??? ?? ?????????????

?1?class?Categories?:?DataAccessObject
?2?
?3?{
?4?????protected?override?void?Select()
?5?????{
?6?????????string?sql?=?"select?CategoryName?from?Categories";
?7?
?8?????????SqlDataAdapter?dataAdapter?=?new?SqlDataAdapter(
?9?
10?????????????sql,?connectionString);
11?
12?????????dataSet?=?new?DataSet();
13?
14?????????dataAdapter.Fill(dataSet,?"Categories");
15?
16?????}
17?
18?????protected?override?void?Display()
19?
20?????{
21?
22?????????Console.WriteLine("Categories?----?");
23?
24?????????DataTable?dataTable?=?dataSet.Tables["Categories"];
25?
26?????????foreach?(DataRow?row?in?dataTable.Rows)
27?
28?????????{
29?
30?????????????Console.WriteLine(row["CategoryName"].ToString());
31?
32?????????}
33?
34?????????Console.WriteLine();
35?
36?????}
37?}

?

?1?class?Products?:?DataAccessObject
?2?
?3?{
?4?????protected?override?void?Select()
?5?
?6?????{
?7?????????string?sql?=?"select?top?10?ProductName?from?Products";
?8?
?9?????????SqlDataAdapter?dataAdapter?=?new?SqlDataAdapter(
10?
11?????????????sql,?connectionString);
12?
13?????????dataSet?=?new?DataSet();
14?
15?????????dataAdapter.Fill(dataSet,?"Products");
16?
17?????}
18?
19?????protected?override?void?Display()
20?
21?????{
22?
23?????????Console.WriteLine("Products?----?");
24?
25?????????DataTable?dataTable?=?dataSet.Tables["Products"];
26?
27?????????foreach?(DataRow?row?in?dataTable.Rows)
28?
29?????????{
30?????????????Console.WriteLine(row["ProductName"].ToString());
31?
32?????????}
33?
34?????????Console.WriteLine();
35?
36?????}
37?
38?}


再來(lái)看看客戶端程序的調(diào)用,不需要再去調(diào)用每一個(gè)步驟的方法:

?1?public?class?App
?2?
?3?{
?4?????static?void?Main()
?5?????{
?6?
?7?????????DataAccessObject?dao;
?8?
?9?
10?????????dao?=?new?Categories();
11?
12?????????dao.Run();
13?
14?
15?????????dao?=?new?Products();
16?
17?????????dao.Run();
18?
19?????????//?Wait?for?user?
20?
21?????????Console.Read();
22?
23?????}
24?
25?}

?

在上面的例子中,需要注意的是:

1.對(duì)于Connect()和Disconnect()方法實(shí)現(xiàn)為了virtual,而Select()和Display()方法則為abstract,這是因?yàn)槿绻@個(gè)方法有默認(rèn)的實(shí)現(xiàn),則實(shí)現(xiàn)為virtual,否則為abstract。

2.Run()方法作為一個(gè)模版方法,它的一個(gè)重要特征是:在基類里定義,而且不能夠被派生類更改。有時(shí)候它是私有方法(private method),但實(shí)際上它經(jīng)常被聲明為protected。它通過調(diào)用其它的基類方法(覆寫過的)來(lái)工作,但它經(jīng)常是作為初始化過程的一部分被調(diào)用的,這樣就沒必要讓客戶端程序員能夠直接調(diào)用它了。

3.在一開始我們提到了不管讀的是哪張數(shù)據(jù)表,它們都有共同的操作步驟,即共同點(diǎn)。因此可以說Template Method模式的一個(gè)特征就是剝離共同點(diǎn)。
Template Mehtod實(shí)現(xiàn)要點(diǎn):

1.Template Method模式是一種非常基礎(chǔ)性的設(shè)計(jì)模式,在面向?qū)ο笙到y(tǒng)中有著大量的應(yīng)用。它用最簡(jiǎn)潔的機(jī)制(虛函數(shù)的多態(tài)性)為很多應(yīng)用程序框架提供了靈活的擴(kuò)展點(diǎn),是代碼復(fù)用方面的基本實(shí)現(xiàn)結(jié)構(gòu)。

2.除了可以靈活應(yīng)對(duì)子步驟的變化外,“不用調(diào)用我,讓我來(lái)調(diào)用你(Don't call me ,let me call you)”的反向控制結(jié)構(gòu)是Template Method的典型應(yīng)用。“Don’t call me.Let me call you”是指一個(gè)父類調(diào)用一個(gè)子類的操作,而不是相反。

3.在具體實(shí)現(xiàn)方面,被Template Method調(diào)用的虛方法可以具有實(shí)現(xiàn),也可以沒有任何實(shí)現(xiàn)(抽象方法,純虛方法),但一般推薦將它們?cè)O(shè)置為protected方法。

總結(jié)

以上是生活随笔為你收集整理的31模板方法(Template Method)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。