c# - 如何抽象一个单例类?

标签 c# design-patterns singleton

这就是我编写单例类的方式。

public class MyClass
{
    /// <summary>
    /// Singleton
    /// </summary>
    private static MyClass instance;

    /// <summary>
    /// Singleton access.
    /// </summary>
    public static MyClass Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new MyClass();
            }
            return _instance;
        }
    }

    private MyClass() { .... }
}

如何创建可重用的单例模式?

单例模式带来了以下挑战。

  • 构造函数是privateprotected
  • 基类不能实例化继承类。因此,您可以重用通用抽象 MyAbstractSingletonClass
  • 它必须具有本地只读属性才能获取实例。

问题

我在许多类中使用了这种模式,并且总是必须编写相同的代码。当我需要单例时,如何编写可以重用的东西?

最佳答案

您可以使用 self-referencing generic type constraint 的组合来实现此目的, 和一个“new()”类型约束。

"new"约束确保任何子类都将始终具有无参数构造函数,因此 _instance = new T(); 将始终有效。

自引用类型约束确保“实例”静态属性始终返回正确的类型;不是“基本”类型。你的单例基类看起来像这样:

public abstract class SingletonBase<T> 
    where T : SingletonBase<T>, new()
{
    private static T _instance = new T();
    public static T Instance
    {
        get
        {                
            return _instance;
        }   
    }
}

您的子类将如下所示:

public class MyChildSingleton : SingletonBase<MyChildSingleton>
{
    //Done!
}

当然,如果你希望你的单例是通用的,你也应该稍微改变你的“创建单例实例”代码,使用“double-check lock”模式,或者Lazy。类,使其成为线程安全的。

重要警告:如果您使用此方法,“new()”约束几乎可以确保您的类始终具有公共(public)的、无参数的构造函数。这意味着如果您的最终用户确实需要,他们总是可以调用 new MyChildSingleton(),完全绕过您的单例实例。您的单例将是“按照惯例”,而不是严格执行。要解决这个问题需要更多的工程。在上面的场景中,惯例似乎是您应该将静态实例命名为“Default”而不是“Instance”。这巧妙地传达了这样一个事实,即您的类提供了一个“建议的”单例实例,但使用它在技术上是可选的。

我做了一些尝试来严格执行单例模式,最终结果是使用反射手动调用私有(private)构造函数。你可以看到我的完整代码尝试 here .

关于c# - 如何抽象一个单例类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16745629/

相关文章:

java - Java 8 中的功能类级别参数

c# - 这是什么设计模式?

C++ Singleton被实例化两次 - 静态成员变量的问题

c# - StreamReader 缓冲带有 GZIP 的流式 HTTP?

c# - .NET Core Web API 作为 Azure 应用服务上的虚拟应用程序

c# - WinForms Designer 自动创建的事件处理程序

c# - 如何在页面刷新 (F5) 时保留隐藏字段的值

c++ - 实现低优先级后台线程的模式?

java - 在java中使用反射调用Singleton类中的方法

ios - 核心数据堆栈与 iCloud 应用程序上的托管文档