C#单例模式的十八般兵器:让对象“独一无二”的终极秘籍

一、基础兵器谱:懒汉式单例

1.1 基础版(线程不安全)

“皇帝还没起床,就被群臣吵醒”

public class SingletonLazy_Basic  
{  
    // 私有构造函数:防止外部new  
    private SingletonLazy_Basic() {}  

    // 共享实例:初始为null  
    private static SingletonLazy_Basic _instance;  

    // 全局访问点:第一次调用时创建实例  
    public static SingletonLazy_Basic Instance  
    {  
        get  
        {  
            if (_instance == null)  
            {  
                _instance = new SingletonLazy_Basic();  // 线程不安全!  
            }  
            return _instance;  
        }  
    }  
}  

注释:

  • 致命缺陷:多线程下可能创建多个实例(就像皇帝还没登基,就被多个大臣同时加冕!)。
  • 适用场景:单线程程序,或“懒人模式”(懒到连锁都不上)。

1.2 线程安全版(双重检查锁定)

“皇帝起床前先锁宫门”

public class SingletonLazy_ThreadSafe  
{  
    private static readonly object _lock = new object();  
    private static SingletonLazy_ThreadSafe _instance;  

    private SingletonLazy_ThreadSafe() {}  

    public static SingletonLazy_ThreadSafe Instance  
    {  
        get  
        {  
            // 第一次检查:避免频繁加锁  
            if (_instance == null)  
            {  
                lock (_lock)  // 加锁:确保线程安全  
                {  
                    if (_instance == null)  // 第二次检查  
                    {  
                        _instance = new SingletonLazy_ThreadSafe();  
                    }  
                }  
            }  
            return _instance;  
        }  
    }  
}  

注释:

  • 双重检查:先不加锁检查,避免频繁加锁的性能损耗。
  • 锁对象_lock 是私有静态对象,防止外部干扰。
  • 性能警告:加锁可能拖慢程序(就像皇帝每次开门都要验明正身)。

二、进阶兵器:饿汉式单例

2.1 基础版(静态初始化)

“皇帝出生时就坐龙椅”

public class SingletonEager  
{  
    // 静态构造函数:类加载时立即初始化  
    static SingletonEager()  
    {  
        _instance = new SingletonEager();  
    }  

    // 私有构造函数  
    private SingletonEager() {}  

    // 直接返回预创建的实例  
    public static SingletonEager Instance => _instance;  

    private static readonly SingletonEager _instance;  
}  

注释:

  • 优点:线程安全,无需锁(一出生就是皇帝)。
  • 缺点:可能提前占用资源(比如皇帝还没登基就建了宫殿)。

2.2 泛型版饿汉式(万能钥匙)

“一把钥匙开所有门”

public class Singleton<T> where T : class, new()  
{  
    private static readonly T _instance = new T();  

    private Singleton() {}  // 防止外部实例化  

    public static T Instance => _instance;  
}  

// 使用示例:  
var logger = Singleton<Logger>.Instance;  
var config = Singleton<Config>.Instance;  

注释:

  • 泛型约束new() 确保T有无参构造函数。
  • 适用场景:需要多个单例类时(比如日志、配置管理器)。

三、终极兵器:静态类单例

“皇帝直接化身为神”

public static class SingletonStatic  
{  
    // 静态方法/属性直接使用  
    public static void DoSomething()  
    {  
        Console.WriteLine("朕乃静态神!");  
    }  

    // 无法实例化(连皇帝的影子都没有)  
    private SingletonStatic() {}  
}  

注释:

  • 优点:绝对线程安全,零资源浪费。
  • 缺点:无法继承或实现接口(就像神不能有子嗣)。

四、秘籍升级:序列化与单例

“皇帝的画像不能变成另一个皇帝!”

[Serializable]  
public class SingletonSerializable : ISerializable  
{  
    private SingletonSerializable() {}  

    private static readonly SingletonSerializable _instance = new SingletonSerializable();  

    public static SingletonSerializable Instance => _instance;  

    // 防止反序列化生成新实例  
    protected SingletonSerializable(SerializationInfo info, StreamingContext context)  
    {  
        throw new InvalidOperationException("皇帝不能被复制!");  
    }  

    public void GetObjectData(SerializationInfo info, StreamingContext context)  
    {  
        throw new NotSupportedException();  
    }  
}  

注释:

  • 反序列化陷阱:默认序列化会破坏单例性。
  • 解决方案:重写 ISerializable 接口并抛异常(就像皇帝的画像不能当真皇帝用)。

五、性能对比实验

“比武大会:哪种单例更快?”

// 测试代码:  
var sw = Stopwatch.StartNew();  
for (int i = 0; i < 1000000; i++)  
{  
    var instance = SingletonLazy_ThreadSafe.Instance;  // 测试对象  
}  
Console.WriteLine($"耗时:{sw.ElapsedMilliseconds} ms");  

// 结果示意:  
// 饿汉式:12ms  
// 懒汉式(线程安全):28ms  
// 静态类:8ms  

注释:

  • 结论:静态类最快,但功能受限;饿汉式平衡性能与灵活性。
  • 彩蛋:在ASP.NET中,HttpContext.Current 就是单例模式的典范!

“单例不是懒汉,是武林至尊!”

通过本文的十八般兵器,你已掌握:

  1. 基础与进阶实现(懒汉、饿汉、静态类)
  2. 线程安全与性能优化
  3. 泛型与序列化陷阱

下一步挑战

  • 用单例模式实现一个“宇宙级日志系统”
  • 设计一个支持热更新的单例配置管理器
  • 写个“单例模式的自毁程序”(防作弊用)

让单例“会说话”

public class ChattySingleton  
{  
    private static readonly ChattySingleton _instance = new ChattySingleton();  

    private ChattySingleton()  
    {  
        Console.WriteLine("朕已诞生!");  
    }  

    public static ChattySingleton Instance => _instance;  

    public void SayHello()  
    {  
        Console.WriteLine("你好啊,朕是单例!");  
    }  
}  

// 使用时:  
ChattySingleton.Instance.SayHello();  
// 输出:  
// 朕已诞生!  
// 你好啊,朕是单例!  

你可能感兴趣的:(C#学习资料,c#,单例模式,javascript)