Comment puis-je faire une classe abstraite qui obligera chaque classe dérivée à Singleton? J'utilise c #. P>
7 Réponses :
Cela ne fonctionnerait pas car le singleton a besoin d'un accès statique et qui ne peut pas être forcé. P>
pour singletonImplemention + exemples Voir: Mise en œuvre du modèle singleton en C # p>
L'article est vraiment brillant. J'avais atteint une conclusion que cela ne sera pas possible, mais je cherche toujours des idées.
Pour référence, le lien mis à jour est le suivant: CSHARPINDEPTH.COM/Articles/General/singleton.aspx
singleton signifie avoir des constructeurs privés. Mais vous savez que les députés ne peuvent être hérités. En C ++, il y avait des modèles, vous pouvez donc créer un singleton à partir d'une classe de modèle. Dans C #, il n'y a pas de modèles, vous devez donc écrire vos propres constructeurs privés pour chaque singleton que vous souhaitez. P>
Lorsque vous souhaitez appliquer la vérification du temps de compilation, cela n'est pas possible. Avec la vérification de l'exécution, vous pouvez le faire. Ce n'est pas joli, mais c'est possible. Voici un exemple:
Ce n'est pas un singleton. Avec le modèle singleton, votre appel à getinstance code> réussira toujours. Votre proposition est en effet simplement un chèque d'exécution qui ne fournit aucun bénéfice du modèle singleton.
Les classes en Java ou C # ne sont pas "de première classe". La partie statique d'une classe ne peut être ni héritée ni remplacée par des sous-classes. Voir Cette réponse pour plus de détails. De plus, vous n'avez pas de concept de méta-classe. P>
Dans des langues comme Smalltalk ou Ruby, vous pouvez définir une nouvelle métaclass singleton code> qui définit une méthode getinstance code>. Ensuite, vous pouvez définir classa code> et classb code> être des instances du singleton code> métaclass. Ensuite, les deux classes exposent automatiquement une méthode getInstance code> qui peut être utilisée pour créer des instances objeta code> ou objetb code>. N'est-ce pas cool? Eh bien, dans la pratique, vous n'utilisez pas de métaclasse fréquemment, et le singleton est en fait la seule utilisation d'eux qui a du sens et que je suis au courant. P>
Bravo pour mentionner SmallTalk
Voici une façon (laide) de faire cela. Il pourrait probablement être simplifié et amélioré, mais c'est mon premier aller à cela.
L'idée est d'abord de faire de la classe de base une classe abstraite générique (comme mentionné dans les commentaires ci-dessus), mais le paramètre Type est contraint de dériver de la classe de base elle-même. Cela permet à la classe de base de gérer l'instance singleton du type dérivé. Remarque Toutes les classes dérivées doivent être scellées, comme avec n'importe quelle classe Singleton. P>
Suivant, un constructeur protégé est autorisé, mais est nécessaire pour accepter une instance d'une classe spéciale, SingletonKey, qui est un singleton modifié. Les classes dérivées ont accès à la définition de classe SingletonKey, mais la classe de base conserve un contrôle privé sur la seule instance autorisée et donc sur la construction de tous les objets dérivés. P>
Troisième, la classe de base devra être capable de Appelez le constructeur de la classe dérivée, mais cela est légèrement délicat. Le compilateur se plaint si vous essayez d'appeler le constructeur à clé dérivé, car il n'est pas garanti d'exister. La solution consiste à ajouter un délégué statique selon lequel la classe dérivée doit initialiser. Toutes les classes dérivées devront donc fournir une méthode d'initialisation simple. Cette méthode d'initialisation doit être appelée explicitement avant de tenter d'accéder à l'instance pour la première fois dans le code ou une erreur d'exécution résultera. P>
public abstract class Singleton<T> where T : Singleton<T>
{
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<SingletonKey, T> Creator;
private static T instance;
public static T Instance
{
get
{
if (instance == null) instance = Creator(Key);
return instance;
}
}
}
public class MySingleton : Singleton<MySingleton>
{
public string Name { get; set; }
public static void Initialize()
{
Creator = (key) => new MySingleton(key);
}
protected MySingleton(SingletonKey key) : base(key)
{
}
}
Je crois que j'ai essayé d'atteindre quelque chose de similaire I.e. Appliquer une interface commune et le modèle singleton sur un groupe de classes. C'était ma solution: Voici un test simple: p> Veuillez noter que vous pouvez facilement supprimer l'interface commune du générique. Classe de Singleton abstrait si vous avez juste besoin du "modèle" de base. p> p>
Ici, ma mise en œuvre de Singleton Héritage:
using System;
using System.Reflection;
namespace Mik.Singleton
{
class Program
{
static void Main()
{
//You can not create an instance of class directly
//Singleton1 singleton1 = new Singleton1();
Singleton1 singleton1 = Singleton1.Instance;
Singleton2 singleton2 = Singleton2.Instance;
Console.WriteLine(singleton1.Singleton1Text);
Console.WriteLine(singleton2.Singleton2Text);
Console.ReadLine();
}
}
public class SingletonBase<T> where T : class
{
#region Singleton implementation
private static readonly object lockObj = new object();
private static T _instance;
protected SingletonBase() { }
public static T Instance
{
get
{
if (_instance == null)
{
lock (lockObj)
{
if (_instance == null)
_instance = CreateInstance();
}
}
return _instance;
}
}
private static T CreateInstance()
{
ConstructorInfo constructor = typeof(T).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null, new Type[0],
new ParameterModifier[0]);
if (constructor == null)
throw new Exception(
$"Target type is missing private or protected no-args constructor: {typeof(T).FullName}");
try
{
T instance = constructor.Invoke(new object[0]) as T;
return instance;
}
catch (Exception e)
{
throw new Exception(
"Failed to create target: type=" + typeof(T).FullName, e);
}
}
#endregion Singleton implementation
}
public class Singleton1 : SingletonBase<Singleton1>
{
private Singleton1() { }
public string Singleton1Text { get; } = "Singleton1Text value";
}
public class Singleton2 : SingletonBase<Singleton2>
{
private Singleton2() { }
public string Singleton2Text { get; } = "Singleton2Text value";
}
}
Avez-vous besoin que cela soit abstrait? Vous pouvez créer une classe générique singleton. Bien qu'il soit toujours possible d'instancher des objets de type T.
Oui. La base abstraite doit forcer les sous-classes à être singleton.