显示页面讨论反向链接回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== C# 单例模式 (Singleton Pattern) ====== 单例模式是 C# 开发中最常用的设计模式之一。它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。 ===== 1. 为什么使用单例模式? ===== 在 C# 应用程序中,单例模式通常用于管理共享资源,例如: * **数据库连接池** * **日志记录器 (Logger)** * **配置文件管理器 (Configuration Manager)** * **硬件接口访问(如打印机后台处理程序)** ===== 2. 实现单例模式的关键点 ===== 要实现一个标准的单例类,必须满足以下条件: - **私有构造函数**:防止外部通过 `new` 关键字创建实例。 - **私有静态变量**:用于持有类的唯一实例。 - **公共静态方法/属性**:提供全局访问点(通常命名为 `Instance`)。 ===== 3. C# 中的几种实现方式 ===== 在 C# 中实现单例有多种方式,主要区别在于**线程安全性**和**延迟加载 (Lazy Loading)** 的处理。 ==== 3.1. 简单的线程不安全实现 (Bad) ==== 这是最基本的实现,但在多线程环境下是**不安全**的。如果两个线程同时判断 `_instance == null`,可能会创建两个实例。 <code csharp> public class Singleton { private static Singleton _instance; // 私有构造函数 private Singleton() { } public static Singleton Instance { get { // 线程不安全! if (_instance == null) { _instance = new Singleton(); } return _instance; } } } </code> ==== 3.2. 简单的线程安全实现 (加锁) ==== 通过 `lock` 关键字确保同一时间只有一个线程执行创建实例的代码。 <code csharp> public 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; } } } } </code> ==== 3.3. 双重检查锁定 (Double-Check Locking) ==== 这种方式既保证了线程安全,又避免了每次访问都加锁带来的性能损耗。只有在实例未创建时才加锁。 <code csharp> public class Singleton { private static Singleton _instance; private static readonly object _lock = new object(); private Singleton() { } public static Singleton Instance { get { // 第一次检查:如果已经创建,直接返回,避免加锁 if (_instance == null) { lock (_lock) { // 第二次检查:防止多个线程同时通过了第一次检查 if (_instance == null) { _instance = new Singleton(); } } } return _instance; } } } </code> ==== 3.4. 静态初始化 (饿汉式) ==== 利用 .NET CLR 的特性,静态构造函数只会执行一次。这种方式非常简单且线程安全,但缺点是**不支持延迟加载**(类一加载,实例就被创建,即使你还没用到它)。 <code csharp> public sealed class Singleton { // CLR 保证了静态字段初始化的线程安全性 private static readonly Singleton _instance = new Singleton(); // 显式静态构造函数告诉 C# 编译器不要将类型标记为 BeforeFieldInit static Singleton() { } private Singleton() { } public static Singleton Instance { get { return _instance; } } } </code> ==== 3.5. 使用 System.Lazy<T> (推荐) ==== 在 .NET 4.0 及更高版本中,这是**最推荐**的实现方式。它利用 `System.Lazy<T>` 类型自动处理线程安全和延迟加载,代码简洁且高效。 <code csharp> public sealed class Singleton { // Lazy<T> 默认是线程安全的 private static readonly Lazy<Singleton> _lazy = new Lazy<Singleton>(() => new Singleton()); private Singleton() { } public static Singleton Instance { get { return _lazy.Value; } } } </code> ===== 4. 总结 ===== ^ 实现方式 ^ 线程安全 ^ 延迟加载 ^ 复杂度 ^ 推荐指数 ^ | 简单实现 | No | Yes | 低 | 不推荐 | | 简单加锁 | Yes | Yes | 中 | 一般 | | 双重检查锁定 | Yes | Yes | 高 | 一般 | | 静态初始化 | Yes | No | 低 | 推荐 (如果不需要延迟加载) | | **System.Lazy<T>** | **Yes** | **Yes** | **低** | **强烈推荐** | ===== 5. 注意事项 ===== - **单一职责原则**:单例类除了管理自己的实例外,通常还承担具体的业务功能。要注意不要让单例类变得过于臃肿。 - **测试困难**:单例模式通常持有全局状态,这使得单元测试变得困难(难以模拟和重置状态)。在需要高度可测试性的系统中,通常建议使用**依赖注入 (Dependency Injection)** 容器来管理单例的生命周期,而不是手动实现单例模式。 登录 Detach Close 该主题尚不存在 您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。 csharp/gof23种设计模式/单例模式.txt 最后更改: 2025/12/29 11:22由 张叶安 登录