C# 中的单例设计模式2024年8月29日 | 阅读 7 分钟 单例设计模式 是 C# 中的一种创建型设计模式。其主要目的是确保一个类只有一个实例,同时提供对该实例的全局访问点。当您想控制对共享资源的访问或确保单个对象协调应用程序中的操作时,此模式非常有用。 C# 中的单例设计模式确保一个类的单个实例被创建并提供对其的全局访问。它的时间和空间复杂度通常是常数(O(1)),这使得它能够有效地管理共享资源,例如配置文件或数据库连接。当使用双重锁定实现时,该模式可以强制执行线程安全的创建。 但是,它简化了对单个实例的访问,开发人员应谨慎使用它,以避免引入全局状态并保持其代码库中关注点的清晰分离。单例模式仍然是解决需要集中控制和协调的特定设计挑战的宝贵工具。 单例模式的常见用例数据库连接池:在与数据库交互的应用程序中,您可以使用单例来管理连接池,确保连接的有效使用。 日志记录:单例日志记录器类可以确保所有日志消息都定向到一个日志文件或目标。 配置管理:当您希望应用程序中的配置设置保持一致时,单例可以存储并提供对这些设置的访问。 缓存:管理常用数据的缓存可以受益于单例模式,以维护单个缓存实例。 单例设计模式的结构C# 中单例模式的结构有几个关键点。单例设计模式的一些主要组成部分如下: 私有构造函数:该类有一个私有构造函数,以防止从外部代码直接实例化。 私有静态实例变量:它包含该类的单个实例,通常标记为静态以确保共享访问。 获取实例的静态方法:提供一个公共静态方法来访问单个实例。此方法可确保在实例不存在时创建实例,或返回现有实例。 单例设计模式的特点单例设计模式具有几个定义其行为和目的的关键特征。理解这些特征对于在软件设计中有效地实现和使用单例模式至关重要。 单个实例:单例模式最根本的特征是它确保在应用程序的整个生命周期中只有一个类的实例。这意味着无论您请求单例实例多少次,您始终获得相同的、单个实例。 全局访问:单例提供对其单个实例的全局访问点。这意味着代码的任何部分都可以访问单例实例,而无需传递引用。这种全局访问简化了与单例对象交互的过程。 私有构造函数:单例类通常有一个私有构造函数来强制执行单个实例规则。它阻止外部代码使用new 关键字创建类的其他实例。私有构造函数是区分单例和常规类的关键功能之一。 延迟初始化:在许多实现中,单例实例仅在首次请求时创建。这被称为延迟初始化。延迟初始化可以提高性能,因为单例直到需要时才被创建。当单例在应用程序的生命周期中未被使用时,它有助于节省资源。 静态实例变量:单例类通常包含一个私有静态变量,该变量保存单个实例。此变量确保实例在所有访问它的代码之间共享。它通常命名为“instance”或类似名称。 程序让我们以一个示例来演示 C# 中的单例设计模式 输出 Both r?f?r?nc?s point to th? sam? Singl?ton instanc?. Data from Singl?ton: Initial data Modifi?d data from Singl?ton: N?w data 说明 using System;:这是一个重要的语句,允许您使用System 命名空间中的类型和方法。 public sealed class Singleton:这是 Singleton 类的声明。它被声明为 sealed 以防止继承,确保不会创建派生类。 private static volatile Singleton instance:这是一个私有静态变量实例,用于保存 Singleton 类的单个实例。它被标记为volatile,以确保一个线程所做的更改对其他线程立即可见。 private static object syncRoot = new Object();:这是一个用于锁定目的的对象,以确保在创建单例实例时线程安全。 private Singleton():私有构造函数确保没有外部代码可以使用new 关键字创建 Singleton 类的实例。它强制执行单个实例规则。 public static Singleton GetInstance():这是一个公共静态方法,提供对单例实例的访问。在该方法内部,它检查实例是否为 null。如果为 null,它会进入锁定块以确保一次只有一个线程创建实例。这被称为双重锁定。如果实例在锁定内仍然为 null,它将创建 Singleton 实例。即使在多线程环境中,此模式也能确保只创建一个实例。 public string GetData():此方法允许您检索单例实例的someData字段。 public void SetData(string data):此方法允许您修改单例实例的someData字段。 这个 Program 类演示了单例模式的用法
当您运行此程序时,您应该会看到如下所示的输出。 复杂性分析时间复杂度 单例模式实现的时间复杂度通常是O(1),表示常数时间复杂度。这适用于关键操作: 创建单例实例 (GetInstance() 方法):创建单例实例是一个常数时间操作,因为它在应用程序的整个执行过程中只发生一次,无论调用 GetInstance() 的次数有多少。GetInstance() 内的逻辑涉及简单的 null 检查,在某些情况下,还包括用于线程安全的锁。这些操作不依赖于数据的大小或方法的调用频率。 访问数据 (GetData() 和 SetData() 方法):访问或修改单例实例内的数据通常也是O(1)。这些方法直接访问类字段(someData),该字段的执行时间不随输入大小或方法调用的数量而变化。 锁定机制:GetInstance() 方法中使用 lock 语句引入了同步,以确保线程安全。锁定和释放锁被认为是O(1)。但是,在高度并发的情况下,线程争用可能会影响时间复杂度。平均而言,复杂度保持不变。 空间复杂度 单例模式实现的空间复杂度也为O(1),表示恒定的空间使用。关键组件包括: 单例实例 (instance):存储单例实例需要恒定的空间。无论调用 GetInstance() 多少次,始终只有一个实例,内存占用量保持固定。 附加数据成员(例如 someData):单例类中附加数据成员的空间复杂度取决于它们的特性。在提供的代码中,someData 是一个字符串,其空间复杂度取决于字符串的长度。通常,类字段的空间复杂度为O(1),除非它们涉及可变大小的集合或数组。 锁定机制(例如 syncRoot):用于锁定的 syncRoot 对象的空间复杂度也是恒定的。它是对固定大小对象的引用,其内存使用不会随输入而改变。 下一个主题C# 中将 double 转换为 int |
我们请求您订阅我们的新闻通讯以获取最新更新。