9

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

class Singleton
{

    private static Singleton _instance;
    public static Singleton Instance => _instance ??= new Singleton();

    protected Singleton() { }
}

这适用于 type 的实例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;

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

  • 派生类可以实现自己的构造函数而失去单例模式。
  • 如果有另一个实例,Singleton则派生类将引用该派生较少的实例

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

4

2 回答 2

24

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

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> { /* .... */ }

但是,我个人并不提倡这种单例方法。它们确实有它们的(罕见的)用途,但它们可能会变得更加痛苦 - 转向美化的全局变量容器。

另外,请注意线程安全。

于 2013-05-31T20:28:15.733 回答
5

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

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

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

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

单例模式很容易正确实现(顺便说一下,您的示例没有 - 它不是线程安全的)那么为什么要有基类呢?基类本身不会是单例(可能会有很多实例——每个子类一个),那么有什么好处呢?

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

如果你真的想要一个基类,那应该是因为所有子类都自然继承了一些共同的功能。这不太可能这些子类是否是单例有关。

于 2013-05-31T20:33:44.227 回答