13.2 常见设计模式(单例、工厂、观察者等)
设计模式概述
设计模式是软件开发中针对常见问题的可重用解决方案。它们代表了最佳实践,是经验丰富的开发人员在长期实践中总结出来的。在C#中,设计模式可以帮助我们编写更清晰、更灵活、更易于维护的代码。
创建型模式
单例模式 (Singleton)
目的:确保一个类只有一个实例,并提供全局访问点。
C#实现:
public sealed class Singleton
{
private static Singleton _instance;
private static readonly object _lock = new object();
private Singleton() { }
public static Singleton Instance
{
get
{
lock (_lock)
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
// 其他业务方法
public void DoSomething()
{
// ...
}
}
使用场景:
- 配置管理器
- 日志记录器
- 数据库连接池
工厂模式 (Factory)
目的:定义一个创建对象的接口,但让子类决定实例化哪个类。
简单工厂示例:
public interface IProduct
{
void Operation();
}
public class ConcreteProductA : IProduct
{
public void Operation() => Console.WriteLine("Product A operation");
}
public class ConcreteProductB : IProduct
{
public void Operation() => Console.WriteLine("Product B operation");
}
public class ProductFactory
{
public IProduct CreateProduct(string type)
{
return type switch
{
"A" => new ConcreteProductA(),
"B" => new ConcreteProductB(),
_ => throw new ArgumentException("Invalid product type", nameof(type))
};
}
}
工厂方法模式:
public abstract class Creator
{
public abstract IProduct FactoryMethod();
public void SomeOperation()
{
var product = FactoryMethod();
product.Operation();
}
}
public class ConcreteCreatorA : Creator
{
public override IProduct FactoryMethod() => new ConcreteProductA();
}
public class ConcreteCreatorB : Creator
{
public override IProduct FactoryMethod() => new ConcreteProductB();
}
结构型模式
适配器模式 (Adapter)
目的:将一个类的接口转换成客户希望的另一个接口。
示例:
// 现有接口
public interface ITarget
{
void Request();
}
// 需要适配的类
public class Adaptee
{
public void SpecificRequest() => Console.WriteLine("Specific request");
}
// 适配器
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public void Request()
{
_adaptee.SpecificRequest();
}
}
行为型模式
观察者模式 (Observer)
目的:定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新。
C#实现:
// 使用.NET内置的IObserver<T>和IObservable<T>
public class Subject : IObservable<string>
{
private readonly List<IObserver<string>> _observers = new();
public IDisposable Subscribe(IObserver<string> observer)
{
_observers.Add(observer);
return new Unsubscriber(_observers, observer);
}
public void NotifyObservers(string message)
{
foreach (var observer in _observers)
{
observer.OnNext(message);
}
}
private class Unsubscriber : IDisposable
{
private readonly List<IObserver<string>> _observers;
private readonly IObserver<string> _observer;
public Unsubscriber(List<IObserver<string>> observers, IObserver<string> observer)
{
_observers = observers;
_observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
_observers.Remove(_observer);
}
}
}
public class Observer : IObserver<string>
{
public void OnNext(string value) => Console.WriteLine($"Received: {value}");
public void OnError(Exception error) => Console.WriteLine($"Error: {error.Message}");
public void OnCompleted() => Console.WriteLine("Completed");
}
策略模式 (Strategy)
目的:定义一系列算法,封装每个算法,并使它们可以互换。
示例:
public interface ISortStrategy
{
void Sort(List<int> list);
}
public class QuickSort : ISortStrategy
{
public void Sort(List<int> list) => Console.WriteLine("Quick sorting");
}
public class MergeSort : ISortStrategy
{
public void Sort(List<int> list) => Console.WriteLine("Merge sorting");
}
public class Sorter
{
private ISortStrategy _strategy;
public Sorter(ISortStrategy strategy)
{
_strategy = strategy;
}
public void SetStrategy(ISortStrategy strategy)
{
_strategy = strategy;
}
public void Sort(List<int> list)
{
_strategy.Sort(list);
}
}
设计模式的选择与实践
- 不要过度设计:只在真正需要时使用设计模式
- 理解模式背后的思想:比记住具体实现更重要
- 结合C#语言特性:如委托、事件、LINQ等可以简化某些模式的实现
- 考虑性能影响:某些模式可能带来额外的开销
现代C#中的模式实现
C#语言特性使某些模式的实现更加简洁:
// 使用记录类型(record)实现不可变对象模式
public record ImmutablePerson(string Name, int Age);
// 使用模式匹配简化策略模式
public decimal CalculateDiscount(object customer) => customer switch
{
PremiumCustomer p => p.OrderTotal * 0.2m,
RegularCustomer r => r.OrderTotal * 0.1m,
_ => 0m
};
总结
设计模式是提高代码质量的有力工具,但需要根据具体场景合理选择。在C#开发中,结合语言特性可以更优雅地实现各种模式。掌握常见设计模式将帮助你编写更灵活、更易维护的应用程序。
