第2课设计模式_单例模式
热度🔥:69 免费课程
授课语音
单例模式(Singleton Pattern)
1. 介绍
单例模式是一种设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
单例模式的核心概念
- 唯一性:确保一个类只有一个实例。即使多个线程尝试创建该类的对象,也只会存在一个实例。
- 全局访问:单例模式提供一个全局访问点来获取这个唯一实例,通常通过静态方法实现,以便在任何地方都可以访问该实例。
- 延迟初始化:在一些实现中,单例实例在第一次被请求时才被创建,这样可以避免不必要的开销。这一过程称为延迟初始化(lazy initialization)。
单例模式的变体
- 懒汉式单例(Lazy Initialization):在第一次被访问时创建实例,优点是延迟初始化,但需要处理多线程环境下的同步问题。
- 饿汉式单例(Eager Initialization):在类加载时就创建实例,这种方式简单且线程安全,但如果实例创建的开销较大而应用从未使用该实例,则可能会造成资源浪费。
- 双重检查锁(Double-Check Locking):在多线程环境下,通过双重检查和锁机制来确保实例创建的线程安全性。通常结合
volatile
关键字使用以避免指令重排序带来的问题。 - 登记式单例(Registry-based Singleton):使用注册表管理单例实例。通过静态方法或其他机制从注册表中获取单例实例,适合需要支持动态实例管理的场景。
- 枚举单例(Enum Singleton):使用枚举类型实现单例模式,这是 Java 推荐的实现方式,能够确保线程安全,并防止反序列化攻击。
实际框架中的应用
单例模式在许多实际框架和系统中有广泛的应用。以下是一些常见的应用场景:
配置管理:在C#框架中,配置管理类通常使用单例模式。例如,ASP.NET Core中的
IConfiguration
接口通常在整个应用程序中共享,以确保配置的一致性。数据库连接池:数据库连接池通常使用单例模式来管理连接。例如,Dapper或Entity Framework等ORM框架在其实现中可能会使用单例模式,以确保高效管理数据库连接。
日志记录:C#中的日志记录器通常使用单例模式来确保日志记录的一致性。例如,NLog或Serilog可以配置为单例,以便在整个应用程序中共享同一个日志记录器实例。
缓存系统:缓存系统如MemoryCache或Redis通常使用单例模式,以确保在整个应用程序中只有一个缓存实例,从而提高性能和资源利用率。
ASP.NET应用:在ASP.NET框架中,服务的默认生命周期可以配置为单例,以确保在整个应用程序上下文中只存在一个实例,从而保证共享的服务和配置的一致性。
这些场景展示了单例模式在C#平台上的广泛应用,能够有效管理资源和提供一致性。
2. 代码案例
using System;
using System.Collections.Generic;
using System.Threading;
public class SingletonExamples
{
// 1. 饿汉式单例(Eager Initialization)
public class EagerSingleton
{
// 在类加载时就创建实例,确保线程安全
private static readonly EagerSingleton Instance = new EagerSingleton();
private string value;
// 私有构造方法,防止外部实例化
private EagerSingleton()
{
value = "EagerSingleton Value";
}
// 提供全局访问点
public static EagerSingleton GetInstance()
{
return Instance;
}
// 显示实例的值
public void ShowValue()
{
Console.WriteLine("EagerSingleton value: " + value);
}
}
// 2. 懒汉式单例(Lazy Initialization)
public class LazySingleton
{
private static LazySingleton instance; // 存储单例实例
private static readonly object lockObject = new object(); // 锁对象
private string value;
// 私有构造方法
private LazySingleton()
{
value = "LazySingleton Value";
}
// 提供全局访问点,使用懒加载方式
public static LazySingleton GetInstance()
{
if (instance == null) // 第一次检查
{
lock (lockObject) // 加锁确保线程安全
{
if (instance == null) // 第二次检查
{
instance = new LazySingleton();
}
}
}
return instance;
}
// 显示实例的值
public void ShowValue()
{
Console.WriteLine("LazySingleton value: " + value);
}
}
// 3. 双重检查锁(Double-Check Locking)
public class DoubleCheckLockingSingleton
{
private static DoubleCheckLockingSingleton instance; // 存储单例实例
private static readonly object lockObject = new object(); // 锁对象
private string value;
// 私有构造方法
private DoubleCheckLockingSingleton()
{
value = "DoubleCheckLockingSingleton Value";
}
// 提供全局访问点,使用双重检查锁机制
public static DoubleCheckLockingSingleton GetInstance()
{
if (instance == null) // 第一次检查
{
lock (lockObject) // 加锁
{
if (instance == null) // 第二次检查
{
instance = new DoubleCheckLockingSingleton();
}
}
}
return instance;
}
// 显示实例的值
public void ShowValue()
{
Console.WriteLine("DoubleCheckLockingSingleton value: " + value);
}
}
// 4. 登记式单例(Registry-based Singleton)
public class RegistrySingleton
{
private static readonly Dictionary<string, RegistrySingleton> registry = new Dictionary<string, RegistrySingleton>(); // 注册表
private string value;
// 私有构造方法
private RegistrySingleton()
{
value = "RegistrySingleton Value";
}
// 提供全局访问点,通过键从注册表获取实例
public static RegistrySingleton GetInstance(string key)
{
if (!registry.ContainsKey(key))
{
registry[key] = new RegistrySingleton(); // 动态管理单例
}
return registry[key];
}
// 显示实例的值
public void ShowValue()
{
Console.WriteLine("RegistrySingleton value: " + value);
}
}
// 5. 枚举单例(Enum Singleton)
public enum EnumSingleton
{
INSTANCE; // 定义唯一的枚举实例
private string value;
// 枚举构造方法
EnumSingleton()
{
value = "EnumSingleton Value";
}
// 显示实例的值
public void ShowValue()
{
Console.WriteLine("EnumSingleton value: " + value);
}
}
// 示例代码
public static void Main(string[] args)
{
// 1. 饿汉式单例
EagerSingleton eager1 = EagerSingleton.GetInstance();
EagerSingleton eager2 = EagerSingleton.GetInstance();
eager1.ShowValue();
Console.WriteLine("Are both EagerSingleton instances the same? " + (eager1 == eager2));
// 2. 懒汉式单例
LazySingleton lazy1 = LazySingleton.GetInstance();
LazySingleton lazy2 = LazySingleton.GetInstance();
lazy1.ShowValue();
Console.WriteLine("Are both LazySingleton instances the same? " + (lazy1 == lazy2));
// 3. 双重检查锁
DoubleCheckLockingSingleton doubleCheck1 = DoubleCheckLockingSingleton.GetInstance();
DoubleCheckLockingSingleton doubleCheck2 = DoubleCheckLockingSingleton.GetInstance();
doubleCheck1.ShowValue();
Console.WriteLine("Are both DoubleCheckLockingSingleton instances the same? " + (doubleCheck1 == doubleCheck2));
// 4. 登记式单例
RegistrySingleton registry1 = RegistrySingleton.GetInstance("key1");
RegistrySingleton registry2 = RegistrySingleton.GetInstance("key1");
registry1.ShowValue();
Console.WriteLine("Are both RegistrySingleton instances the same? " + (registry1 == registry2));
// 5. 枚举单例
EnumSingleton enumSingleton = EnumSingleton.INSTANCE;
enumSingleton.ShowValue();
}
}
详细中文注释
- 类说明:每个单例实现类都有一个内部初始化方法,用于设置初始值。在每个
ShowValue
方法中打印该实例的值,以验证实例的唯一性。 - 示例代码:在主程序中,我们创建每种单例的两个实例并检查它们是否相同,以证明单例模式的有效性。每个实例调用
ShowValue
方法显示其值。