C# 高级教程 - 17 高级设计模式

基础教程中我们了解过单例、工厂、观察者等经典设计模式。在实际的 C# 项目中,这些模式有更地道的 .NET 实现方式,同时也需要理解模式之间的组合与演进。本文将探讨设计模式在 C# 中的最佳实践以及 .NET 生态中的模式变体。

单例模式 —— .NET 最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 方式 1:静态初始化(推荐 —— 线程安全、惰性、简单)
public sealed class Singleton
{
private static readonly Singleton _instance = new();

// 显式静态构造函数保证 beforefieldinit 语义
static Singleton() { }

private Singleton() { }

public static Singleton Instance => _instance;
}

// 方式 2:Lazy<T>(需要延迟加载复杂初始化时)
public sealed class LazySingleton
{
private static readonly Lazy<LazySingleton> _lazy =
new(() => new LazySingleton(), LazyThreadSafetyMode.ExecutionAndPublication);

private LazySingleton() { }

public static LazySingleton Instance => _lazy.Value;
}

// 方式 3:泛型单例(基类模式,谨慎使用)
public abstract class SingletonBase<T> where T : class, new()
{
private static readonly T _instance = new();
public static T Instance => _instance;
}

工厂模式 —— 现代 C# 风格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 抽象工厂 + DI 风格
public interface IPaymentProvider
{
Task<PaymentResult> ProcessAsync(decimal amount);
string ProviderName { get; }
}

public class AlipayProvider : IPaymentProvider { /* ... */ }
public class WechatPayProvider : IPaymentProvider { /* ... */ }

// 策略模式的工厂
public class PaymentFactory
{
private readonly Dictionary<string, IPaymentProvider> _providers;

public PaymentFactory(IEnumerable<IPaymentProvider> providers)
{
_providers = providers.ToDictionary(p => p.ProviderName);
}

public IPaymentProvider GetProvider(string name)
=> _providers.TryGetValue(name, out var provider)
? provider
: throw new ArgumentException($"不支持的支付方式: {name}");
}

// 注册
services.AddScoped<IPaymentProvider, AlipayProvider>();
services.AddScoped<IPaymentProvider, WechatPayProvider>();
services.AddScoped<PaymentFactory>();

策略模式 —— 函数式简化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 传统策略模式
public interface ISortStrategy
{
int[] Sort(int[] data);
}

public class BubbleSort : ISortStrategy { public int[] Sort(int[] data) { /* ... */ } }
public class QuickSort : ISortStrategy { public int[] Sort(int[] data) { /* ... */ } }

// C# 函数式简化 —— 不再需要接口+类
public class Sorter
{
private readonly Func<int[], int[]> _sortFunc;

public Sorter(Func<int[], int[]> sortFunc)
{
_sortFunc = sortFunc;
}

public int[] Sort(int[] data) => _sortFunc(data);
}

// 使用(无需定义接口和具体策略类)
var sorter = new Sorter(data =>
{
Array.Sort(data);
return data;
});

var sorter2 = new Sorter(data => data.OrderBy(x => x).ToArray());

观察者模式 —— .NET 事件 vs IObservable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// .NET 事件(耦合度较高)
public class StockPublisher
{
public event EventHandler<StockPriceChangedEventArgs>? PriceChanged;

protected virtual void OnPriceChanged(string symbol, decimal price)
{
PriceChanged?.Invoke(this, new StockPriceChangedEventArgs(symbol, price));
}
}

// IObservable<T>(松耦合,支持 LINQ 操作)
public class StockObservable : IObservable<StockPrice>
{
private readonly List<IObserver<StockPrice>> _observers = new();

public IDisposable Subscribe(IObserver<StockPrice> observer)
{
_observers.Add(observer);
return new Unsubscriber(_observers, observer);
}

public void Notify(StockPrice price)
{
foreach (var observer in _observers)
observer.OnNext(price);
}

private class Unsubscriber : IDisposable
{
private readonly List<IObserver<StockPrice>> _observers;
private readonly IObserver<StockPrice> _observer;

public Unsubscriber(List<IObserver<StockPrice>> observers, IObserver<StockPrice> observer)
{
_observers = observers;
_observer = observer;
}

public void Dispose() => _observers.Remove(_observer);
}
}

// 使用 Rx.NET 更简洁
// Install: dotnet add package System.Reactive
Observable.Interval(TimeSpan.FromSeconds(1))
.Select(tick => new StockPrice("AAPL", 150 + Math.Sin(tick) * 5))
.Subscribe(price => Console.WriteLine($"{price.Symbol}: {price.Price:C}"));

建造者模式 —— 流畅 API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class SqlQueryBuilder
{
private readonly StringBuilder _select = new();
private readonly StringBuilder _from = new();
private readonly StringBuilder _where = new();
private readonly StringBuilder _orderBy = new();
private int _take;

public SqlQueryBuilder Select(string columns)
{
_select.Append(columns);
return this;
}

public SqlQueryBuilder From(string table)
{
_from.Append(table);
return this;
}

public SqlQueryBuilder Where(string condition)
{
if (_where.Length > 0)
_where.Append(" AND ");
_where.Append(condition);
return this;
}

public SqlQueryBuilder OrderBy(string column, bool descending = false)
{
_orderBy.Append(column);
if (descending) _orderBy.Append(" DESC");
return this;
}

public SqlQueryBuilder Take(int count)
{
_take = count;
return this;
}

public string Build()
{
var sql = new StringBuilder($"SELECT {_select} FROM {_from}");

if (_where.Length > 0)
sql.Append($" WHERE {_where}");
if (_orderBy.Length > 0)
sql.Append($" ORDER BY {_orderBy}");
if (_take > 0)
sql.Append($" LIMIT {_take}");

return sql.ToString();
}
}

// 使用
string sql = new SqlQueryBuilder()
.Select("Id, Name, Price")
.From("Products")
.Where("Price > 100")
.Where("Stock > 0")
.OrderBy("Price", descending: true)
.Take(10)
.Build();

责任链模式 —— 中间件管道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public interface IHandler
{
Task HandleAsync(OrderContext context, Func<Task> next);
}

public class ValidationHandler : IHandler
{
public async Task HandleAsync(OrderContext context, Func<Task> next)
{
if (context.Order.Amount <= 0)
throw new ValidationException("金额必须大于 0");

Console.WriteLine("验证通过");
await next();
}
}

public class LoggingHandler : IHandler
{
public async Task HandleAsync(OrderContext context, Func<Task> next)
{
Console.WriteLine($"处理订单: {context.Order.Id}");
await next();
Console.WriteLine($"订单处理完成: {context.Order.Id}");
}
}

// 管道构建器
public class PipelineBuilder
{
private readonly List<IHandler> _handlers = new();

public PipelineBuilder Add(IHandler handler)
{
_handlers.Add(handler);
return this;
}

public Func<OrderContext, Task> Build()
{
return async context =>
{
async Task ExecuteAsync(int index)
{
if (index < _handlers.Count)
await _handlers[index].HandleAsync(context,
() => ExecuteAsync(index + 1));
}

await ExecuteAsync(0);
};
}
}

// 使用
var pipeline = new PipelineBuilder()
.Add(new ValidationHandler())
.Add(new LoggingHandler())
.Add(new SaveToDatabaseHandler())
.Build();

await pipeline(new OrderContext { Order = order });

状态模式 —— 游戏/工作流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class OrderStateMachine
{
public IOrderState CurrentState { get; private set; }

public OrderStateMachine()
{
CurrentState = new PendingState();
}

public void Next() => CurrentState = CurrentState.Next();
public void Cancel() => CurrentState = CurrentState.Cancel();
public string Status => CurrentState.Status;

public interface IOrderState
{
string Status { get; }
IOrderState Next();
IOrderState Cancel();
}

public class PendingState : IOrderState
{
public string Status => "待支付";

public IOrderState Next() => new PaidState();
public IOrderState Cancel() => new CancelledState();
}

public class PaidState : IOrderState
{
public string Status => "已支付";

public IOrderState Next() => new ShippedState();
public IOrderState Cancel() => new RefundingState();
}

public class ShippedState : IOrderState
{
public string Status => "已发货";
public IOrderState Next() => new DeliveredState();
public IOrderState Cancel() => new RefundingState();
}

public class DeliveredState : IOrderState
{
public string Status => "已送达";
public IOrderState Next() => this; // 终态
public IOrderState Cancel() => this;
}

public class CancelledState : IOrderState
{
public string Status => "已取消";
public IOrderState Next() => this;
public IOrderState Cancel() => this;
}

public class RefundingState : IOrderState
{
public string Status => "退款中";
public IOrderState Next() => new CancelledState();
public IOrderState Cancel() => this;
}
}

适配器模式 —— 兼容旧接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 旧的第三方日志接口
public class ThirdPartyLogger
{
public void LogMessage(string message, int level)
{
Console.WriteLine($"[Level {level}] {message}");
}
}

// 标准日志接口
public interface ILogger
{
void Info(string message);
void Error(string message, Exception? ex = null);
}

// 适配器
public class LoggerAdapter : ILogger
{
private readonly ThirdPartyLogger _adaptee;

public LoggerAdapter(ThirdPartyLogger adaptee) => _adaptee = adaptee;

public void Info(string message)
=> _adaptee.LogMessage(message, 0);

public void Error(string message, Exception? ex = null)
=> _adaptee.LogMessage($"{message}: {ex}", 1);
}

C# 中设计模式演变趋势

模式 传统 C# 实现 现代 C# 实现
策略 接口 + 多态类 Func/Action 委托
工厂 抽象工厂类 DI + Func 工厂
观察者 事件 (event) IObservable/IObserver + Rx
建造者 具体 Builder 类 记录+with 表达式
模板方法 抽象基类 高阶函数
访问者 双分发访问者 模式匹配 (switch)

总结:设计模式是重构的”词汇表”,而非一成不变的模板。在 C# 中,许多传统模式可以被更简洁的语言特性替代(委托替代策略,record 替代 DTO/建造者),而另一些模式(DI 容器、中间件管道)已成为框架基础设施。理解模式的本质意图,在 .NET 生态中选择最地道的实现方式,比僵硬地套用 GoF 模板更重要。

ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: