抽象基类强制每个派生类为Singleton

如何创建一个抽象类来强制每个派生类为Singleton? 我用C#。

如果要编译时间检查,则无法进行此操作。 通过运行时检查,您可以执行此操作 它不漂亮,但它是可能的。 这是一个例子:

public abstract class Singleton { private static readonly object locker = new object(); private static HashSet registeredTypes = new HashSet(); protected Singleton() { lock (locker) { if (registeredTypes.Contains(this.GetType())) { throw new InvalidOperationException( "Only one instance can ever be registered."); } registeredTypes.Add(this.GetType()); } } } public class Repository : Singleton { public static readonly Repository Instance = new Repository(); private Repository() { } } 

这是行不通的,因为单身人士需要静态访问,而且不能强迫。

对于singletonimplemention +示例,请参阅: 在C#中实现Singleton模式

Singleton意味着拥有私有构造函数。 但是你知道私人成员不能被inheritance。 在C ++中有模板,因此您可以从模板类创建单例。 在C#中,没有模板,所以你必须为你想要的每个单独编写自己的私有构造函数。

这是一种(丑陋的)方式。 它可能会被简化和改进,但这是我第一次采用它。

我们的想法是首先使基类成为通用抽象类(如上面的注释中所述),但类型参数被约束为从基类本身派生。 这允许基类处理派生类型的单例实例。 请注意,所有派生类都应该密封,就像任何单例类一样。

接下来,允许使用受保护的构造函数,但是需要接受特殊类SingletonKey的实例,SingletonKey是一个修改过的单例。 派生类可以访问SingletonKey类定义,但基类保留对唯一允许的实例的私有控制,从而保留对所有派生对象的构造。

第三,基类需要能够调用派生类的构造函数,但这有点棘手。 如果您尝试调用派生的键控构造函数,编译器将会抱怨,因为它不能保证存在。 解决方案是添加派生类必须初始化的静态委托。 因此任何派生类都需要提供一个简单的初始化方法。 在尝试在代码中第一次访问实例之前,应该显式调用此初始化方法,否则将导致运行时错误。

 public abstract class Singleton where T : Singleton { protected Singleton(SingletonKey key) { } private static SingletonKey _key; private static SingletonKey Key { get { if (_key == null) SingletonKey.Initialize(); return _key; } } protected class SingletonKey { private SingletonKey() { } public static void Initialize() { if (_key == null) { _key = new SingletonKey(); } } } protected static Func Creator; private static T instance; public static T Instance { get { if (instance == null) instance = Creator(Key); return instance; } } } public class MySingleton : Singleton { public string Name { get; set; } public static void Initialize() { Creator = (key) => new MySingleton(key); } protected MySingleton(SingletonKey key) : base(key) { } } 

java或C#中的类不是“第一类”。 子类的静态部分不能由子类inheritance或覆盖。 有关详细信息,请参阅此答案 。 另外,你没有元类的概念。

在Smalltalk或Ruby等语言中,您可以定义一个新的元类Singleton ,它定义了一个方法getInstance 。 然后,您可以将ClassAClassB定义为Singleton元类的实例。 然后,这两个类自动公开一个方法getInstance ,该方法可用于创建实例objectAobjectB 。 那不是很酷吗? 好吧,在实践中你不经常使用元类,而单例实际上是它们的唯一用法,它是有意义的并且我知道。

我相信我试图实现类似的东西,即在一组类上强制执行通用接口和单例模式。 这是我的解决方案:

 // Common interface of my singleton classes public interface IMySingletonClass { string ValueGetter(); void ValueSetter(string value); } // Generic abstract base class public abstract class Singleton: IMySingletonClass { private static readonly object instanceLock = new object(); private static T instance; // Derived class instance // Protected constructor accessible from derived class protected Singleton() { } // Returns the singleton instance of the derived class public static T GetInstance() { lock (instanceLock) { if (instance == null) { instance = (T)Activator.CreateInstance(typeof(T), true); } return instance; } } // IMySingletonClass interface methods public abstract string ValueGetter(); public abstract void ValueSetter(string value); } // Actual singleton class public class MySingletonClass : Singleton { private string myString; private MySingletonClass() { myString = "Initial"; } public override string ValueGetter() { return myString; } public override void ValueSetter(string value) { myString = value; } } 

这是一个简单的测试:

 class Program { static void Main(string[] args) { MySingletonClass r1 = MySingletonClass.GetInstance(); Console.WriteLine("R1 value = {0}", r1.ValueGetter()); r1.ValueSetter("Changed through R1"); MySingletonClass r2 = MySingletonClass.GetInstance(); Console.WriteLine("R2 value = {0}", r2.ValueGetter()); Console.ReadKey(); } } 

请注意,如果您只需要基本的“模板”,则可以轻松地从通用抽象单例类中删除公共接口。