如果你寫 C# 寫久了,enum 一定是你最早會用、也用最兇的語法之一。
它乾淨、簡單、可讀性好,但只要邏輯稍微複雜一點,
enum 就開始綁手綁腳,大量的 if 或是 switch 又開始了,不利於我們中年工程師..
你常常規劃一些多重的選擇問題+enum 最後一定會變成
switch (method)
{
case PaymentMethod.LinePush:
// ....
break;
case PaymentMethod.Email:
// ....
break;
}
這樣很多商業邏輯都會被封裝在那一顆裡面,因為主要邏輯判斷都在那個大的 function
後來我看一些文章有看到一個不錯的規劃方法,這邊我就簡單筆記一下主要是透過把 enum value 變成物件,讓物件去處理邏輯
大家都稱之為 Smart Enum
這邊我就舉例一個簡單的案例,常遇到的,我們要發送給客戶訊息,但是有分成 Email , SMS , LinePush
1. 寫一個抽象基底這邊我環境是用 用 .NET 9 primary constructor
public abstract class NotificationType
{
public string Name { get; }
protected NotificationType(string name)
{
Name = name;
}
public abstract void Send(string message);
public abstract bool Validate(string input);
public static readonly NotificationType Email = new EmailType();
public static readonly NotificationType Sms = new SmsType();
public static readonly NotificationType PushLine = new PushLineType();
}
static readonly 用來模擬 enum value
2. 寫三個 Smart Enum Value(每個都有自己的行為)
public sealed class EmailType : NotificationType
{
public EmailType() : base("Email") { }
public override bool Validate(string email)
{
//Validate Email Logic
return email.Contains("@");
}
public override void Send(string message)
{
//Send Logic
Console.WriteLine("Send email:" + message);
}
}
public sealed class SmsType : NotificationType
{
public SmsType() : base("SMS") { }
public override bool Validate(string number)
{
//Validate Text Logic
return number.StartsWith("09") && number.Length == 10;
}
public override void Send(string message)
{
Console.WriteLine("Send SMS:" + message);
//Send Logic
}
}
public sealed class PushLineType : NotificationType
{
public PushLineType() : base("PushLine") { }
public override bool Validate(string token)
{
return token.Length > 10;
}
public override void Send(string message)
=> Console.WriteLine($"Send Push: {message}");
}
每個 Smart Enum value 有自己的 驗證邏輯、發送邏輯
3. 接下來就不用 switch 了
var typeSMS = NotificationType.Sms;
if (typeSMS.Validate("0912345678"))
{
typeSMS.Send("Hello! Moto!");
}
var typeLine = NotificationType.PushLine;
if (typeLine.Validate("token-123456789"))
{
typeLine.Send("Hello! LINE!");
}
var typeEmail = NotificationType.Email;
if (typeLine.Validate("foo@sample.com"))
{
typeLine.Send("Hello! EMAIL!");
}
//Send SMS:Hello! Moto!
//Send Push: Hello! LINE!
//Send Push: Hello! EMAIL!
沒有 if、沒有 switch、邏輯全部封裝在類別裡面,而且每個也可以被單一測試維護
結論 -
如果你發現 enum 已經快撐不住你的完美主義的程式,那就改用 Smart Enum。不只是"可以寫得很 OOP"
維護起來比 switch-based 程式乾淨太多