【问题标题】:Singleton Pattern with Public Constructor带有公共构造函数的单例模式
【发布时间】:2009-09-16 09:01:09
【问题描述】:
public class MySingletonClass
{
  public MySingletonClass()
  {
    _mySingletonObj = Instance();
  }

  public static MySingletonClass Instance()
  {
    if (_mySingletonObj  == null)
    {
      lock (typeof(lockObject))
      {
        if (_mySingletonObj  == null)
          _mySingletonObj  = new MySingletonClass();
      }
    }
    return _mySingletonObj ;
  }
}

MySingletonClass _myObj = new MySingletonClass();

这充当带有公共构造函数的单例..?

谢谢

【问题讨论】:

  • 你为什么要那样做?
  • 我认为这段代码会导致死锁和递归构造函数调用 -> 堆栈溢出。
  • 这段代码充满了问题,实际上并不能作为单例运行,因为正如 Oliver 所指出的,公共构造函数也会导致堆栈溢出。

标签: c# singleton


【解决方案1】:

不,它不是单例 - 任何人都可以创建它的多个实例。 (撇开已经提出的堆栈溢出问题,以及您使用不安全的双重检查锁定这一事实。)

单例类型的显着特征之一是它可以防止构造多个自身实例。

来自维基百科Singleton Pattern 文章:

在软件工程中,单例 模式是一种设计模式 用于限制 a 的实例化 归类为一个对象。

来自Ward Cunningham's pattern repository

单例是两个的组合 基本属性:

  • 确保一个类只有一个实例
  • 提供全局访问点

很明显,您的单身人士不符合这两个定义。

查看我的singleton article 了解实际实现。

【讨论】:

    【解决方案2】:

    由于公共构造函数,发布的代码不能作为单例运行,但除此之外,代码还存在许多缺陷和问题:

    • 公共构造函数调用Instance,它调用公共构造函数,它调用Instance,它调用.....堆栈溢出迫在眉睫
    • 公共构造函数每次调用都会返回一个新对象,后续请求时不能用相同的对象引用替换返回的结果。换句话说,单例上的公共构造函数打破了这种模式。
    • 您不应该泄漏您的锁定对象,在您的情况下,您锁定对象的类型。不要那样做,而是锁定一个私有对象。

    这是您的代码的固定版本:

    public class MySingletonClass
    {
      private readonly object _mySingletonLock = new object();
      private volatile MySingletonClass _mySingletonObj;
    
      private MySingletonClass()
      {
        // normal initialization, do not call Instance()
      }
    
      public static MySingletonClass Instance()
      {
        if (_mySingletonObj == null)
        {
          lock (_mySingletonLock)
          {
            if (_mySingletonObj  == null)
              _mySingletonObj = new MySingletonClass();
          }
        }
        return _mySingletonObj;
      }
    }
    
    MySingletonClass _myObj = MySingletonClass.Instance();
    

    【讨论】:

    • 这仍然不是线程安全的 - _mySingletonObj 需要是可变的。
    【解决方案3】:

    查看Dofactory 上的 .NET 优化代码部分。这具有 IMO 的最佳实施。另请查看该站点以了解 C# 中的其他设计模式实现。

    【讨论】:

      【解决方案4】:

      构造函数应该是私有的

      【讨论】:

        【解决方案5】:

        除了锁定它,您还可以尝试创建一个静态只读单例...

        public sealed class Singleton
        {
            private static readonly Singleton instance = new Singleton();
        
            static Singleton()
            {
            }
        
            private Singleton()
            {
            }
        
            /// <summary>
            /// The public Instance property to use
            /// </summary>
            public static Singleton Instance
            {
                get { return instance; }
            }
        }
        

        【讨论】:

          【解决方案6】:

          Singleton 的本质是提供:

          • 整个系统中只有一个类实例;
          • 轻松访问。

          Singleton 的实现基于使用方法(或 .NET 中的属性)创建一个类,如果该类的实例尚不存在,则该方法会创建该类的实例。类的构造函数必须是私有的,以防止其他方式的初始化。此外,在多线程应用程序中必须小心使用单例,因为在某个时间点,两个线程可能会创建两个不同的实例(这违反了单例模式)。

          更多细节和例子你可以找到here.

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-11-15
            • 1970-01-01
            • 2011-02-08
            • 1970-01-01
            • 2017-04-30
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多