Template Method Pattern,顧名思義它就是一個模板,必須要在它指定的框架內完成實作。
所以要使用 Template Method Pattern,可以分為幾個步驟:
- 定義父類別抽象類型,也就是定義框架
- 子類別類型繼承父類別
- 子類別類型實作父類別的抽象方法
定義父類別抽象類型
讓我們以「烹飪」當作範例,首先要定義烹飪會需要完成哪些步驟:
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 58 59 60 61 62 63
|
using System;
namespace TemplateMethodPattern { public abstract class Cooking { public string _dishName;
public Cooking(string dishName) { this._dishName = dishName; }
public abstract void Prepare();
public abstract void Cook();
public void SetDish() { Console.WriteLine($"{this._dishName}好了,可以上菜囉"); }
public void Done() { Console.WriteLine("完成上菜,來整理廚房"); this.CleanUp(); }
private void CleanUp() { Console.WriteLine("廚房整理好了"); } } }
|
實作父類別的抽象方法
今天要做一道辣炒牛肉空心菜,我們建立一個子類別中式料理 ChineseDish
,繼承父類別,並實作父類別的方法:
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
using System; using System.Collections.Generic;
namespace TemplateMethodPattern { public class ChineseDish : Cooking {
private List<string> _ingredients;
public ChineseDish(string dishName) : base(dishName) { }
public override void Prepare() { Console.WriteLine($"今天要來做{this._dishName}");
switch (this._dishName) { case "辣炒牛肉空心菜": this._ingredients = new List<string> { "辣椒", "空心菜", "牛肉" }; break; }
this.Clean();
this.Cut();
Console.WriteLine("材料準備好了"); }
public override void Cook() { Console.WriteLine("中式料理當然要用鍋炒,材料有:{0}", string.Join(",", this._ingredients)); Console.WriteLine("菜煮好了"); }
private void Clean() { Console.WriteLine("菜洗好了"); }
private void Cut() { Console.WriteLine("菜切好了"); } } }
|
最後來看看結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
using System; using System.Collections.Generic;
namespace TemplateMethodPattern { class Program { static void Main(string[] args) { var dish = new ChineseDish("辣炒牛肉空心菜");
dish.Prepare(); dish.Cook(); dish.SetDish(); dish.Done(); } } }
|
輸出結果如下:
1 2 3 4 5 6 7 8 9
| 今天要來做辣炒牛肉空心菜 菜洗好了 菜切好了 材料準備好了 中式料理當然要用鍋炒,材料有:辣椒,空心菜,牛肉 菜煮好了 辣炒牛肉空心菜好了,可以上菜囉 完成上菜,來整理廚房 廚房整理好了
|
完整程式碼請參考
結論
這樣就完成了我們的中式料理,也可以用相同的方式做其他類型的料理。
你可以想像成 Template Method Pattern 就像是你看著食譜做菜,只要照著“食譜”這個框架完成即可。
不過 Template Method Pattern 是一種強烈的繼承關係,違反了 DIP 原則:高層模組不應該相依於低層模組,兩者都應該相依於抽象。下一篇介紹的 Strategy Design Pattern 解決了這個問題。
參考
TEMPLATE METHOD 模式和 STRATEGY 模式.無瑕的程式碼 敏捷完整篇:物件導向原則、設計模式與 C# 實踐
Wiki - Template method pattern
樣板方法模式