设计模式 Singleton

本文探讨了单例模式的几种实现方式,包括通用泛型单例模式及其线程安全处理方法。介绍了如何通过锁机制和嵌套类静态构造来确保多线程环境下单例模式的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

uploads/200703/14_222942_singleton.gif


类别:创建型
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用:
  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
----------------------

单件和工厂估计是最常用的设计模式了,想必每个人都很熟。本贴只是研究一些 Singleton 的"变种"。

1. 通用泛型单件模式
class ClassA
{
}

class ClassB
{
}

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

  public static T Instance
  {
    get
    {
      if (instance == null)
        instance = new T();

      return instance;
    }
  }
}

public class Program
{
  static void Main(string[] args)
  {
    ClassA a1 = Singleton<ClassA>.Instance;
    ClassA a2 = Singleton<ClassA>.Instance;
    Console.WriteLine(object.ReferenceEquals(a1, a2)); // output: true

    ClassB b1 = Singleton<ClassB>.Instance;
    Console.WriteLine(object.ReferenceEquals(a1, b1)); // output: false
  }
}

该方式的好处是:
(1) 支持已有类型
(2) 支持多类型
(3) 无需修改目标类型,用户可以在单件和多实例之间自由选择。

2. 线程安全

大多数单件模式的例子(包括上面的)并没有做线程安全处理,因此在执行 "new Instance()" 时存在一定的隐患。

方式1:Lock
public static class Singleton<T>
  where T : class, new()
{
  private static T instance;
  private static object o = new object();

  public static T Instance
  {
    get
    {
      if (instance == null)
      {
        lock (o)
        {
          if (instance == null)
            instance = new T();
        }
      }

      return instance;
    }
  }
}

注意使用了两次 "instance == null" 判断。因为可能有两个以上的线程进入第一个判断语句,其中一些在 lock 释放后有可能再次执行 "new T()" 操作,因此加上第二个判断避免这种情况发生。

方式2:嵌套类静态构造
public static class Singleton<T>
  where T : class, new()
{
  public static T Instance
  {
    get
    {
      return Nested.instance;
    }
  }

  private class Nested
  {
    internal static T instance = new T();
  }
}

我们知道无论如何,静态构造只会被执行一次,因此自然也就是多线程安全的了。只所以使用嵌套类是因为在需要的时候才初始化该实例,另外不用对外公开这些细节。

另外,需要补充说明的是:

泛型类声明中的静态变量在相同封闭构造类型的所有实例之间共享,但是不会在不同封闭构造类型的实例之间共享。不管静态变量的类型是否涉及任何类型参数,这些规则都适用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值