在C#中实现单例可继承类

时间:2013-05-31 20:24:28

标签: c# inheritance singleton

我发现在C#中你可以实现一个Singleton类,如下所示:

class Singleton
{

    private static Singleton _instance;

    public static Singleton Instance
    {
        get { return _instance ?? (_instance = new Singleton()); }
    }

    protected Singleton() { }
}

适用于Singleton类型的实例,即:

var a = Singleton.Instance;
var b = Singleton.Instance;
Console.WriteLine(ReferenceEquals(a, b)); //Prints True.

但是如果我想要Singleton的派生类也遵循Singleton模式,即:

class A:Singleton
{ ... }
A a = A.Instance;

在这种情况下,Instance类访问静态成员Singleton并创建Singleton实例,这不是目标。 此外,该解决方案存在两个主要问题:

  • 派生类可以实现自己的构造函数并松开Singleton Pattern。
  • 如果有另一个Singleton实例,则派生类将引用较少派生的实例

我的问题是:还有另一种在C#中实现Singleton类的方法,确保派生类也是单例吗?

2 个答案:

答案 0 :(得分:18)

忽略通常的“不要使用单身人士,看看你的设计。”参数,你可以想象实现一个(假设你的派生类有默认的构造函数):

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

    public static T GetInstance()
    {
        if(_instance == null)
            _instance = new T();
        return _instance;
    }
}

并由此得出:

public class SingletonA : Singleton<SingletonA> { /* .... */ }
public class SingletonB : Singleton<SingletonB> { /* .... */ }

但是,我个人并不主张采用这种单身方法。它们确实有它们的(稀有)用途,但它们可能会变得更加痛苦 - 变成美化的全球变量容器。

另外,请注意线程安全。

答案 1 :(得分:3)

  

我的问题是:是否有另一种在C#中实现Singleton类的方法,确保派生类也是单例?

好吧,你可以在构造函数中进行某种检查:

  • this的实际类型已被密封
  • this的实际类型是Singleton
  • 的直接子类
  • 尚未创建该类型的其他实例(通过保留HashSet<Type>

然而,这似乎毫无意义。您的基类实际上意味着什么?

单例模式是easy to implement properly(顺便说一句,你的例子不是 - 它不是线程安全的)所以为什么要有基类?基类本身不是单例(可能有很多实例 - 每个子类一个)所以有什么好处?

在我看来,“我是对象的实际类型的单身人士”首先不是继承的适当基础,坦率地说,我尽量避免使用单身人士模式反正。

如果你真的想要一个基类,那应该是因为所有子类都有一些自然继承的常用功能。对于这些子类是否是单例,这不太可能本身