【Design Pattern】工廠模式

最近阿猩的公司為解決一些問題,在新專案導入了Mediator模式,阿猩從一開始學.NET就有試著閱讀Design Pattern。剛好有這個契機Push自己,日後會花時間,嘗試理解不同Design Pattern,盡量不死記,試著內化成自己可以活用的知識,今天要練習的設計模式為工廠模式

情境說明


假設目前要開發一套傳統計算機的程式,由客戶端輸入2個數字,並選擇計算方式,如加、減、乘、除。


釐清業務需求
回傳計算結果的程式,例如1+1 = 2,會需要完成一些工作,阿猩試著先將工作職責釐清,後續才能分別完成每個職責的程式碼。

例如

  1. 使用者傳入數字及計算方法
  2. 依使用者輸入條件,選擇計算方法。
  3. 各種使用方法的運算過程、或特別判定
  4. 取得計算結果
  5. 顯示計算結果

 

依職責建立物件


使用者傳入數字及計算方法
因阿猩使用.NET Framework主控台應用程式,一開始需要宣告共用變數,儲存使用者輸入的值,包含2個數字、計算方法符號及最後運算結果。

// 1. 宣告變數
decimal num1 = 0;
decimal num2 = 0;
string oper = string.Empty;
decimal result = 0;

// 2. 使用者輸入
console.WriteLine("請輸入第1個數字:");
decimal.TryParse(Console.ReadLine(), out num1);

Console.WriteLine("請輸入計算機操作 (Ex: +,-,*,/):");
oper = Console.ReadLine();

Console.WriteLine("請輸入第2個數字:");
decimal.TryParse(Console.ReadLine(), out num2); 

 

依使用者輸入條件,選擇計算方法。
為了達到職責分離,將判斷計算方式,與取得結果的程式分離,使用者輸入加減乘除時,演算法工廠只需要判斷,接下來要用哪種算法,並產生對應的物件。但因為return類別只能有1個,故需回傳一個業務邏輯的父類別或抽象,可以使用Abstract、Interface、自定義類別,此處阿猩是使用Interface。

 

/// <summary>
/// 演算法工廠
/// </summary>
public class AlgorithmFactory
{
    public static IAlgorithm CreateAlgorithm(string type)
    {
        switch (type)
        {
            case "+":
               return new AddAlgorithm();
            case "-":
               return new SubAlgorithm();
            case "*":
               return new MulAlgorithm();
            case "/":
               return new DivAlgorithm();
            default:
               throw new ApplicationException(string.Format("Algorithm'{0}' cannot be created", type));
        }
    }
}

 

計算的運算過程、或特別判定
產生業務邏輯的物件,如AddAlgorithm、SubAlgorithm等,分別繼承IAlgorithm並實作。

/// <summary>
/// 加法演算法
/// </summary>
class AddAlgorithm : IAlgorithm
{
    public decimal GetResult(decimal num1, decimal num2)
    {
        return num1 + num2;
        }
    }
}

/// <summary>
/// 減法演算法
/// </summary>
class SubAlgorithm : IAlgorithm
{
    public decimal GetResult(decimal num1, decimal num2)
    {
        return num1 - num2;
    }
}


取得計算結果
.NET Framework主控台應用程式的Program,阿猩將其視為WebAPI的Controller,只用於流程控制。呼叫AlgorithmFactory.CreateAlgorithm(oper),根據使用者輸入值,建立計算方法後,帶入2個數字,要用哪種方法計算,及如何算,都與Program無關。

// 3. 工廠模式
IAlgorithm Algorithm = AlgorithmFactory.CreateAlgorithm(oper);
result = Algorithm.GetResult(num1, num2);

 

輸出結果至螢幕

Console.WriteLine(string.Format("{0} {1} {2} = {3}", num1, oper, num2, result));
Console.ReadLine();

 

工廠模式思考重點


  1. 不同業務邏輯寫在各自的Object。
  2. 工廠模式可以解決的問題,是把判斷與實際業務分離。工廠只需要判斷生成哪個Object。
  3. 工廠新增時,Object類型為多到一,為return不同Object,應依賴於抽象或業務的共用父類別。如果畫成UML圖,會像是圖1
  4. New物件時,可定義為父層型別,例如 IAlgorithm iAlgorithm = new AddAlgorithm()
     
圖1 工廠模式UML