Monostate vs. Singleton

Quels sont les scénarios où l’on utiliserait un motif Monostate au lieu de singleton pour maintenir un object global?

Edit: Je sais ce que sont les patterns Singleton et Monostate. Ont également mis en œuvre Singleton dans un certain nombre de scénarios. Je veux juste connaître les scénarios (exemples de cas) où le modèle MonoState doit être implémenté.

Par exemple Je dois maintenir la liste des colonnes par écran dans mon application Windows Forms. Je pourrais utiliser un dictionnaire Singleton dans ce cas. Cependant, je stocke une liste dans la variable statique globale et je voulais fournir des indexeurs (car je dois append dynamicment une nouvelle entrée à la liste si la clé n’est pas présente) où je pourrais spécifier ScreenDetails.ScreenName comme clé et obtenir les ScreenDetails. .ColumnsTable. Comme les indexeurs ne peuvent pas fonctionner sur une classe statique, j’ai changé le modèle en Monostate.

Je voudrais donc savoir quels autres scénarios peuvent contraindre un utilisateur à utiliser Monostate au lieu de Singletons.

À sa base, Monostate est simplement du sucre syntaxique autour de Singleton. Lorsque Monostate devient intéressant, c’est lorsque vous commencez à sous-classer, car les sous-classes peuvent décorer l’état partagé avec un comportement différent.

Un exemple simple – si quelque peu artificiel et peu efficace 🙂 – exemple:

public class GlobalTable implements Iterable { /** Shared state -- private */ private static final Map MAP = new LinkedHashMap(); /** Public final accessor */ public final Value get(Key key) { return MAP.get(key); } /** Public final accessor */ public final boolean put(Key key, Value value) { return MAP.put(key); } /** Protected final accessor -- subclasses can use this to access the internal shared state */ protected final Set keySet() { return MAP.keySet(); } /** Virtual -- subclasses can override for different behavior */ public Iterator iterator() { return Collections.unmodifiableSet(MAP.keySet()).iterator(); } } 

Maintenant, si nous voulons un access indexé?

 public class IndexedGlobalTable extends GlobalTable { public List getKeysAsList() { return Collections.unmodifiableList(new ArrayList(keySet())); } public Key getKeyAt(int index) { return getKeysAsList().get(index); } public Value getValueAt(int index) { return get(getKeyAt(index)); } } 

Qu’en est-il des clés sortingées?

 public class SortedGlobalTable extends GlobalTable { @Override public Iterator  iterator() { return Collections .unmodifiableSortedSet(new TreeSet(keySet())).iterator(); } } 

Chaque fois que vous avez besoin de l’une ou l’autre vue des données, il vous suffit d’instancier la sous-classe appropriée.

Bien sûr, la question de savoir si les données globales sont une bonne idée en premier lieu est une autre question, mais au moins, Monostate vous donne plus de flexibilité dans l’utilisation que vous en faites.

le monostate et le singleton sont deux faces de la même médaille (état global):

  • Monostate force un comportement (une seule valeur le long de toutes les instances de classe)
  • singleton force une contrainte structurelle (une seule instance)

l’utilisation du singleton n’est pas transparente

c’est à dire:

 Singleton singleton = Singleton.getInstance(); 

l’utilisation du monostate est transparente

c’est à dire:

 MonoState m1 = new MonoState(); MonoState m2 = new MonoState(); // same state of m1 

Voici ce que Robert C. Martin a à dire à ce sujet: Singleton vs. Monostate (pdf)

SINGLETON est mieux utilisé lorsque vous voulez limiter une classe existante par dérivation, et cela ne vous dérange pas que tout le monde doive appeler la méthode instance () pour y accéder. Il est préférable d’utiliser Monostate lorsque vous souhaitez que la nature singulière de la classe soit transparente pour les utilisateurs ou lorsque vous souhaitez utiliser des dérivées polymorphes de l’object unique.

Quelqu’un devrait juste noter que les singletons et les monostates sont des modèles extrêmement dangereux. Ils ont tendance à abuser de codeurs paresseux qui ne veulent pas avoir à penser à la durée de vie de l’object qu’ils veulent transformer en singleton. Ils rendent les tests plus difficiles et créent des systèmes rigides étroitement liés.

Il est extrêmement rare de trouver une situation où un singleton ou un monostate est vraiment nécessaire. La méthode préférée de collaboration d’object est l’dependency injections.

Beaucoup a été écrit à ce sujet:

  • accu singleton article anti-modèle
  • scot densmore sur les singltons étant mal
  • surcharge de stack sur singletons

La différence entre les deux modèles est celle du comportement par rapport à la structure. Le motif SINGLETON renforce la structure de la singularité. Il empêche la création de plusieurs instances. Alors que MONOSTATE applique le comportement de la singularité sans imposer de contraintes structurelles.

Avantages du SINGLETON

  • Applicable à toute classe. Vous pouvez changer n’importe quelle classe en SINGLETON simplement en rendant ses constructeurs privés et en ajoutant les fonctions et variables statiques appropriées.
  • Peut être créé par dérivation. Étant donné une classe, vous pouvez créer une sous-classe qui est un SINGLETON.
  • Évaluation paresseuse. Si le SINGLETON n’est jamais utilisé, il n’est jamais créé.

Coûts du SINGLETON

  • La destruction n’est pas définie. Il n’y a pas de bon moyen de détruire ou de mettre hors service un SINGLETON. Si vous ajoutez une méthode de mise hors service qui annule l’instance, d’autres modules du système peuvent toujours contenir une référence à l’instance de SINGLETON. Les appels suivants à l’instance provoquent la création d’une autre instance, ce qui entraîne l’existence de deux instances simultanées.

  • Pas hérité Une classe dérivée d’un SINGLETON n’est pas un singleton. S’il doit s’agir d’un SINGLETON, la fonction statique et la variable doivent y être ajoutées.

  • Efficacité. Chaque appel à une instance appelle l’instruction if. Pour la plupart de ces appels, l’instruction if est inutile.

  • Non transparent Les utilisateurs d’un SINGLETON savent qu’ils utilisent un SINGLETON, car ils doivent appeler la méthode Instance.

Avantages de MONOSTATE

  • Transparence. Les utilisateurs d’un MONOSTATE ne se comportent pas différemment des utilisateurs d’un object normal. Les utilisateurs n’ont pas besoin de savoir que l’object est MONOSTATE.

  • Dérivabilité Les dérivés d’un MONOSTATE sont des MONOSTATES. En effet, tous les dérivés d’un MONOSTATE font partie du même MONOSTATE. Ils partagent tous les mêmes variables statiques.

  • Polymorphisme. Les méthodes d’un MONOSTATE n’étant pas statiques, elles peuvent être remplacées dans un dérivé. Ainsi, différents dérivés peuvent offrir un comportement différent sur le même ensemble de variables statiques.

  • Création et destruction bien définies. Les variables d’un MONOSTATE, statiques, ont des temps de création et de destruction bien définis.

Frais de MONOSTATE

  • Pas de conversion Une classe normale ne peut pas être convertie en une classe MONOSTATE par dérivation.

  • Efficacité. Un MONOSTATE peut traverser de nombreuses créations et destructions car c’est un véritable object. Ces opérations sont souvent coûteuses.

  • Présence. Les variables d’un MONOSTATE prennent de la place, même si le MONOSTATE n’est jamais utilisé.

Développement logiciel agile, principes, modèles et pratiques Robert C. Martin