提到模闆,大家肯定不免想到生活中的“履歷模闆”、“論文模闆”、“Word中模版檔案”等,在現實生活中,模闆的概念就是——有一個規定的格式,然後每個人都可以根據自己的需求或情況去更新它,例如履歷模闆,下載下傳下來的履歷模闆的格式都是相同的,然而我們下載下傳下來履歷模闆之後我們可以根據自己的情況填充不同的内容要完成屬于自己的履歷。在設計模式中,模闆方法模式中模闆和生活中模闆概念非常類似,下面讓我們就詳細介紹模闆方法的定義,大家可以根據生活中模闆的概念來了解模闆方法的定義。
模闆方法模式——在一個抽象類中定義一個操作中的算法骨架(對應于生活中的大家下載下傳的模闆),而将一些步驟延遲到子類中去實作(對應于我們根據自己的情況向模闆填充内容)。模闆方法使得子類可以不改變一個算法的結構前提下,重新定義算法的某些特定步驟,模闆方法模式把不變行為搬到超類中,進而去除了子類中的重複代碼。
了解了模闆方法的定義之後,自然實作模闆方法也不是什麼難事了,下面以生活中炒蔬菜為例來實作下模闆方法模式。在現實生活中,做蔬菜的步驟都大緻相同,如果我們針對每種蔬菜類定義一個燒的方法,這樣在每個類中都有很多相同的代碼,為了解決這個問題,我們一般的思路肯定是把相同的部分抽象出來到抽象類中去定義,具體子類來實作具體的不同部分,這個思路也正式模闆方法的實作精髓所在,具體實作代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<code>// 用戶端調用</code>
<code> </code><code>class</code> <code>Client</code>
<code> </code><code>{</code>
<code> </code><code>static</code> <code>void</code> <code>Main(</code><code>string</code><code>[] args)</code>
<code> </code><code>{</code>
<code> </code><code>// 建立一個菠菜執行個體并調用模闆方法</code>
<code> </code><code>Spinach spinach = </code><code>new</code> <code>Spinach();</code>
<code> </code><code>spinach.CookVegetabel();</code>
<code> </code><code>Console.Read();</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>abstract</code> <code>class</code> <code>Vegetabel</code>
<code> </code><code>// 模闆方法,不要把模版方法定義為Virtual或abstract方法,避免被子類重寫,防止更改流程的執行順序</code>
<code> </code><code>public</code> <code>void</code> <code>CookVegetabel()</code>
<code> </code><code>Console.WriteLine(</code><code>"抄蔬菜的一般做法"</code><code>);</code>
<code> </code><code>this</code><code>.pourOil();</code>
<code> </code><code>this</code><code>.HeatOil();</code>
<code> </code><code>this</code><code>.pourVegetable();</code>
<code> </code><code>this</code><code>.stir_fry();</code>
<code> </code><code>// 第一步倒油</code>
<code> </code><code>public</code> <code>void</code> <code>pourOil()</code>
<code> </code><code>Console.WriteLine(</code><code>"倒油"</code><code>);</code>
<code> </code><code>// 把油燒熱</code>
<code> </code><code>public</code> <code>void</code> <code>HeatOil()</code>
<code> </code><code>Console.WriteLine(</code><code>"把油燒熱"</code><code>);</code>
<code> </code><code>// 油熱了之後倒蔬菜下去,具體哪種蔬菜由子類決定</code>
<code> </code><code>public</code> <code>abstract</code> <code>void</code> <code>pourVegetable();</code>
<code> </code><code>// 開發翻炒蔬菜</code>
<code> </code><code>public</code> <code>void</code> <code>stir_fry()</code>
<code> </code><code>Console.WriteLine(</code><code>"翻炒"</code><code>);</code>
<code> </code><code>// 菠菜</code>
<code> </code><code>public</code> <code>class</code> <code>Spinach : Vegetabel</code>
<code> </code>
<code> </code><code>public</code> <code>override</code> <code>void</code> <code>pourVegetable()</code>
<code> </code><code>Console.WriteLine(</code><code>"倒菠菜進鍋中"</code><code>);</code>
<code> </code><code>// 大白菜</code>
<code> </code><code>public</code> <code>class</code> <code>ChineseCabbage : Vegetabel</code>
<code> </code><code>{ </code>
<code> </code><code>Console.WriteLine(</code><code>"倒大白菜進鍋中"</code><code>);</code>
在上面的實作中,具體子類中重寫了導入蔬菜種類的方法,因為這個真是燒菜方法中不同的地方,是以由具體子類去實作它。
實作完模闆方法模式之後,讓我們看看模闆方法的類圖結構,以理清該模式中類之間的關系,具體類圖如下:
模闆方法模式中涉及了兩個角色:
抽象模闆角色(Vegetable扮演這個角色):定義了一個或多個抽象操作,以便讓子類實作,這些抽象操作稱為基本操作。
具體模闆角色(ChineseCabbage和Spinach扮演這個角色):實作父類所定義的一個或多個抽象方法。
下面讓我們繼續分析下模闆方法的優缺點。
優點:
實作了代碼複用
能夠靈活應對子步驟的變化,符合開放-封閉原則
缺點:因為引入了一個抽象類,如果具體實作過多的話,需要使用者或開發人員需要花更多的時間去理清類之間的關系。
附:在.NET中模闆方法的應用也很多,例如我們在開發自定義的Web控件或WinForm控件時,我們隻需要重寫某個控件的部分方法。
到這裡,模闆方法的介紹就結束了,模闆方法模式在抽象類中定義了算法的實作步驟,将這些步驟的實作延遲到具體子類中去實作,進而使所有子類複用了父類的代碼,是以模闆方法模式是基于繼承的一種實作代碼複用的技術。
<a href="http://down.51cto.com/data/2363674" target="_blank">附件:http://down.51cto.com/data/2363674</a>
本文轉自LearningHard 51CTO部落格,原文連結:http://blog.51cto.com/learninghard/1316446,如需轉載請自行聯系原作者