根據字符串 methodName 執行不同邏輯,返回字符串結果。
// 1. 介面
public interface IMethodHandler
{
string Execute();
}
// 2. 具體實現
public class GetHandler : IMethodHandler
{
public string Execute() => "get";
}
public class GetTestHandler : IMethodHandler
{
public string Execute() => "gettest";
}
public class GetSetHandler : IMethodHandler
{
public string Execute() => "getset";
}
// 3. 工廠(可擴展為字典/反射/自動註冊)
public static class MethodFactory
{
private static readonly Dictionary> _map = new(StringComparer.OrdinalIgnoreCase)
{
["get"] = () => new GetHandler(),
["gettest"] = () => new GetTestHandler(),
["getset"] = () => new GetSetHandler(),
};
public static IMethodHandler Create(string name)
{
if (_map.TryGetValue(name, out var factory))
return factory();
throw new ArgumentException($"Unknown method: {name}");
}
}
// 4. 調用
public string Exec(string methodName)
{
var handler = MethodFactory.Create(methodName);
return handler.Execute();
}
private static readonly Dictionary> _actions = new(StringComparer.OrdinalIgnoreCase)
{
["get"] = () => "get",
["gettest"] = () => "gettest",
["getset"] = () => "getset",
};
public string Exec(string methodName)
{
return _actions.TryGetValue(methodName, out var action) ? action() : throw new ArgumentException($"Unknown: {methodName}");
}
public interface IStrategy
{
string Name { get; }
string Execute(Context ctx);
}
public class GetStrategy : IStrategy
{
public string Name => "get";
public string Execute(Context ctx) => "get"; // 可訪問 ctx 共享數據
}
public class StrategyContext
{
private readonly IEnumerable _strategies;
public StrategyContext(IEnumerable strategies) => _strategies = strategies;
public string Execute(string name, Context ctx)
{
var strategy = _strategies.FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
return strategy?.Execute(ctx) ?? throw new ArgumentException($"No strategy: {name}");
}
}
// DI 註冊:services.AddTransient(); 等
// 控制器構造注入 StrategyContext
public abstract class MethodBase
{
public abstract string Name { get; }
public abstract string Execute();
}
public class GetMethod : MethodBase
{
public override string Name => "get";
public override string Execute() => "get";
}
// 使用:List methods = ...;
// methods.First(m => m.Name == name).Execute();
public string Exec(string methodName) => methodName.ToLowerInvariant() switch
{
"get" => "get",
"gettest" => "gettest",
"getset" => "getset",
_ => throw new ArgumentException($"Unknown: {methodName}")
};
// 類型模式匹配
public string Process(object input) => input switch
{
int i => $"Int: {i}",
string s => $"String: {s}",
DateTime dt => $"Date: {dt:yyyy-MM-dd}",
null => "Null",
_ => "Other"
};
// 屬性模式
public string Describe(User u) => u switch
{
{ Role: "Admin", IsActive: true } => "Active Admin",
{ Role: "User", LastLogin: var login } when login > DateTime.Now.AddDays(-30) => "Active User",
_ => "Guest"
};
public static IMethodHandler CreateByReflection(string name)
{
// 約定:命名空間 + 名稱 + "Handler",程序集名
string typeName = $"MyApp.Handlers.{name.FirstCharToUpper()}Handler";
var type = Type.GetType(typeName) ?? Assembly.Load("MyApp.Handlers").GetType(typeName);
return (IMethodHandler)Activator.CreateInstance(type);
}
// 擴展方法
public static string FirstCharToUpper(this string s) =>
string.IsNullOrEmpty(s) ? s : char.ToUpper(s[0]) + s[1..];
| 場景 | 推薦模式 | 理由 |
|---|---|---|
| 簡單映射、無狀態、高性能 | 字典委託 | O(1) 查找、零分配、極簡 |
| 邏輯複雜、需依賴注入、可測試 | 策略模式 + DI | 單一職責、易 Mock、生命週期可控 |
| 插件系統、動態載入、配置驅動 | 反射/工廠 + 約定 | 運行時發現、無需重新編譯宿主 |
| 領域建模、行為與數據封裝 | 多態 | 豐富領域模型、消除基元類型癡迷 |
| 少量分支、代碼局部、追求簡潔 | Switch Expression | 語法簡潔、編譯器優化、可擴展模式匹配 |
if-else 鏈代替 Switch —— 同樣違反 OCP,可讀性更差。Type 每次 Activator.CreateInstance —— 性能差,應緩存工廠委託 Func。Execute 方法 —— 退化為「上帝類」。掌握這五種模式,即可在代碼審查中自信地重構「巨大 Switch」,讓業務邏輯清晰、可測、可擴展。