前言
上一篇文章寫了如何使用RabbitMQ做個簡單的傳送郵件專案,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的訊息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧!
在瞭解簡單工廠模式之前,我們要知道C#是一款物件導向的高階程式語言。它有3大特性,封裝、繼承、多型。
簡述
工廠模式(Factory Pattern)是一種常用的設計模式,屬於建立型模式,它提供了一種建立物件的最佳方式。在工廠模式中,我們建立物件時不會對客戶端暴露建立邏輯,並且是透過使用一個共同的介面來指向新建立的物件。
工廠模式的核心是定義一個建立產品物件的工廠介面,將實際建立工作推遲到子類當中。這樣客戶端可以無需指定具體產品的類,只需透過工廠類即可得到所需的產品物件。
工廠模式主要分為三種型別:簡單工廠模式(Simple Factory Pattern)、工廠方法模式(Factory Method Pattern)和抽象工廠模式(Abstract Factory Pattern)。
本文主要講解簡單工廠模式(Simple Factory Pattern)。
案例帶入
下面使用C#控制檯程式去寫一個簡易的計算器,實現加減乘除。如果我沒學過設計模式,我會這麼寫:
static void Main(string[] args)
{
Console.WriteLine("請輸入數字A:");
string A = Console.ReadLine();
Console.WriteLine("請選擇運算子號:(+、-、*、/):");
string op = Console.ReadLine();
Console.WriteLine("請輸入數字B:");
string B = Console.ReadLine();
string result = "";
switch (op)
{
case "+":
result = Convert.ToString(Convert.ToDouble(A) + Convert.ToDouble(B));
break;
case "-":
result = Convert.ToString(Convert.ToDouble(A) - Convert.ToDouble(B));
break;
case "*":
result = Convert.ToString(Convert.ToDouble(A) * Convert.ToDouble(B));
break;
case "/":
result = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(B));
break;
default:
Console.WriteLine("輸入的運算子號有誤!");
break;
}
Console.WriteLine("結果:" + result);
}
上述程式碼乍一看沒問題,實則隱藏了很多陷阱,比如:
- 變數命名不規範
- 除數為0怎麼辦
- 輸入的不是數字怎麼辦
- ......
最佳化
我們用物件導向的思想進行最佳化,主要體現在:可維護、可複用、可擴充套件、靈活性幾個方面。透過封裝、繼承、多型來降低程式的耦合度。
封裝
我們可以將運算邏輯封裝成一個方法去實現,讓主方法減輕負擔。封裝後:
Operation
類
public class Operation
{
public static double GetResult(double num1, double num2, string op)
{
double result = 0d;
switch (op)
{
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
result = num1 * num2;
break;
case "/":
result = num1 / num2;
break;
}
return result;
}
}
Main
方法
static void Main(string[] args)
{
try
{
Console.WriteLine("請輸入數字A:");
string strNumA = Console.ReadLine();
Console.WriteLine("請選擇運算子號:(+、-、*、/):");
string op = Console.ReadLine();
Console.WriteLine("請輸入數字B:");
string strNumB = Console.ReadLine();
string result = "";
result = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumA), Convert.ToDouble(strNumB), op));
Console.WriteLine("結果:" + result);
}
catch (Exception e)
{
Console.WriteLine("發生異常:" + e.Message);
}
}
松耦合
當我們完成封裝後開始思考一個問題,如果後面有新的需求,需要增加一個開根執行,應該如何去修改?如果是我,我會在switch裡面加一個分支,但是這樣耦合度太高。我明明只需要去開根,但是卻要讓加減乘除參與進來,所以我們應該將加減乘除運算分離出來。
最佳化耦合度:
public class Operation
{
private double _num1;
private double _num2;
public double Num1 { get => _num1; set => _num1 = value; }
public double Num2 { get => _num2; set => _num2 = value; }
public virtual double GetResult()
{
return 0;
}
}
//加法類
public class AddOperation : Operation
{
public override double GetResult()
{
return Num1 + Num2;
}
}
//減法類
public class SubtractOperation : Operation
{
public override double GetResult()
{
return Num1 - Num2;
}
}
//乘法類
public class MultiplyOperation : Operation
{
public override double GetResult()
{
return Num1 * Num2;
}
}
//除法類
public class DivideOperation : Operation
{
public override double GetResult()
{
if (Num2 == 0)
throw new DivideByZeroException("除數不能為0");
return Num1 / Num2;
}
}
我建立了Operation
基類,並定義了2個成員變數_num1
和_num2
,同時定義了一個GetResult
虛方法。同時分別建立了加減乘除子類去重寫GetResult
方法來降級耦合度。
迴歸正題(簡單工廠模式)
我們需要透過簡單工廠模式,來讓程式知道該例項化誰。需要來建立一個工廠類:
public class OperationFactory
{
public static Operation CreateOperation(string operation)
{
switch (operation)
{
case "+":
return new AddOperation();
case "-":
return new SubtractOperation();
case "*":
return new MultiplyOperation();
case "/":
return new DivideOperation();
default:
return null;
}
}
}
建立了工廠類有什麼好處呢,好處就是,只需要輸入運算子號,工廠就能自己例項化出合適的物件,透過多型,返回父類的方法實現了計算器的計算結果。
Main
方法
透過簡單工廠模式,讓我們在計算加減乘除的時候只需要去增加對應的子類就行了,下面的程式碼進行加法執行時,透過傳入+號讓工廠去幫我們例項化子類。
static void Main(string[] args)
{
try
{
// 簡單工廠模式
var oper = OperationFactory.CreateOperation("+");
oper.Num1 = 10;
oper.Num2 = 5;
Console.WriteLine(oper.GetResult());
}
catch (Exception e)
{
Console.WriteLine("發生異常:" + e.Message);
}
}
類圖
講完簡單工廠模式後,簡簡單單復現一下類圖:
小小知識點
- 介面:強調“做什麼”,即介面定義了物件應該做什麼,而不關心它是如何做的。
- 虛方法:強調“如何做”,即基類提供了一種實現方式,但允許派生類根據需要進行修改。
參考資料
- 熟讀並反覆背誦大話設計模式-程傑出版