延續昨天的例子,我們在製作飲料的過程中,其實整體步驟都是蠻相像的,不外乎就是先煮沸水,加入茶葉煮成茶,加入冰塊以及配料,最後封膜打包給客人,這一系列的流程很類似,可能就差在使用的茶葉是甚麼,或者某些品項需要做一點額外變化。
下面我們就要利用抽象類別來幫助我們建立好一系列的SOP,至於實作的細節就交給繼承類別來實作,最後在抽象類別中用類似 Facade 的方式把所有步驟的流程包進一個方法裡,這樣就能夠在主程式中,就能夠建立不同實作類別,但用同個方法名稱來完成製作飲料的過程。
定義一個操作中演算法的骨架,而將一些步驟延遲到子類別中。不改變演算法的結構而重定義它的步驟。
(圖片來源: https://upload.wikimedia.org/wikipedia/commons/2/2a/Template_Method_UML_class_diagram.svg)
using System;
namespace DAY15_Template
{
class Program
{
static void Main(string[] args)
{
// 製作綠茶
Drink greenTea = new GreenTea();
// 使用 Drink 中包裝好的方法
greenTea.Prepare();
Console.WriteLine("---------");
// 製作紅茶
Drink blackTea = new BlackTea();
blackTea.Prepare();
Console.ReadLine();
}
}
// 綠茶
public class GreenTea : Drink
{
// 改寫加入綠茶茶包
public override void AddIngredients()
{
Console.WriteLine("加入綠茶包");
}
}
// 紅茶
public class BlackTea : Drink
{
// 改寫加入紅茶茶包
public override void AddIngredients()
{
Console.WriteLine("加入紅茶包");
}
}
public abstract class Drink
{
// 共用方法,包裝其他定義好的方法
public void Prepare()
{
BoilWater();
AddIngredients();
Pour();
}
public abstract void AddIngredients();
private void BoilWater()
{
Console.WriteLine("開始者熱水");
}
private void Pour()
{
Console.WriteLine("把煮好的茶倒入杯子");
}
}
}
Template Method模式可以用來去除重複,我們用一個基礎類別實作步驟序列,然後對每種情況都用自己的衍生類別實作法,要真正地實作這一點,需要填充一些細節。
首先,衍生類別中的步驟需要在基礎類別中宣告為抽象和/或保護方法。其次,在步驟之間需要使用局部方法變數。這些變數有的需要作為參數傳入,有的作為返回值,也有的是類別的資料成員。各步驟公共的變數應該放在基礎類別中。