9
votes

Je veux une alternative de conception à un singleton

Je me rends compte qu'il y a beaucoup de discussions sur les singletons et pourquoi cela sont mauvais. Ce n'est pas la question de cette question. Je comprends les inconvénients à singletons.

J'ai un scénario où l'utilisation d'un singleton est facile et semble avoir un sens. Cependant, je veux une alternative qui accomplira ce dont j'ai besoin sans beaucoup de frais généraux. P>

Notre application est conçue comme un client qui fonctionne généralement sur des ordinateurs portables dans le champ et communique avec un serveur arrière. Nous avons une barre d'état au bas de l'application principale. Il contient quelques zones de texte qui montrent diverses statues et informations ainsi que plusieurs icônes. Les icônes changent leur image pour indiquer leur état. Telle qu'une icône GPS indique s'il est connecté ou non aussi bien que l'état d'erreur. P>

Notre classe principale est appelée Mobilemain. Il possède la zone de barre d'état et est responsable de la créer. Nous avons ensuite une classe StatusBarManager. Le StatusBarmanager est actuellement une classe statique, mais pourrait également être un singleton. Voici le début de la classe. P>

public static class StatusBarManager
{
    static ScreenStatusBar StatusBar;

    /// <summary>
    /// Creates the status bar that it manages and returns it.
    /// </summary>
    public static ScreenStatusBar CreateStatusBar()
    {
        StatusBar = new ScreenStatusBar();
        return StatusBar;
    }


8 commentaires

Cet article a un certain nombre de questions. Choisissez-en un à la fois pour vous y avoir répondu.


Avez-vous pensé à utiliser Mef ou Unity? Vous enregistrez une seule instance de tout ce que vous voulez avec un conteneur afin que vous puissiez la récupérer ailleurs.


Une bonne lecture, liée à la nommée de StatusBarmanager; codinghorror.com/blog/2006/03/ ...


L'inversion du principe de contrôle entre en jeu ici. Je dirais que vous devriez inverser la dépendance de vos 20 classes de 20+ à StatusBarmanager. Un moyen de faire ce serait le modèle d'observateur, où le StatusBarmanager observe et répond aux changements d'état en conséquence (un épargggrengator serait un moyen de y parvenir).


Singleton n'est pas toujours mauvais, Fwiw. Si vous avez le problème, Singleton est censé résoudre, l'utiliser. Son a obtenu un mauvais rap cependant parce que les gens ont essayé d'utiliser Singleton en dehors du problème qu'il tente de résoudre, ce qui causerait une catastrophe avec tout modèle de conception.


Patrick, merci, nous utilisons beaucoup quelque chose deManager. Dans certains cas, il convient que les classes effectuent de nombreuses actions, mais nous devrions peut-être enfreindre la classe dans des classes plus spécialisées. Je renommerai notre classe à Statubarupdater, car il est uniquement responsable de la mise à jour de la barre d'état.


Mattttavavey, comment voudriez-vous le mettre à la hauteur. Chaque classe qui mettraita-t-elle à jour la barre d'état doit mettre en œuvre et l'événement que la barre d'état s'abonnerait à. Ensuite, les classes effectuant la mise à jour augmenteraient cet événement? Si tel est le cas, cela crée beaucoup de codage pour des événements et signifie également que le statut de Status devrait connaître à tous ceux qui la met à jour pour souscrire à leurs événements. Je n'ai pas encore mis en œuvre un éparggregator, je viens de lire à leur sujet, serait-il utile d'investir le temps d'apprendre à leur sujet? Fournissent-ils beaucoup d'usage?


@WPFnewbie affirmative sur votre premier point. Cela nécessiterait une pensée sérieuse pour résumer tous ces événements de telle sorte qu'ils puissent tous être traités de la même manière (bien que répondu au différent) par le statut de StatusBarmanager. Également affirmative sur votre deuxième point, mais l'éparggregator vous permettrait deux de casser le couplage serré entre StatusBarmanager et les plus de sujets de statut. Vous pouvez utiliser DI pour injecter la mise en œuvre de l'agrégateur d'événement (en tant que singleton géré par le conteneur DI) dans le StatusBarManager et les plus de 20 Updateurs respectivement.


5 Réponses :


3
votes

Je préfère des classes statiques qui contiennent vos objets. Donc, la quantité d'objets que vous pouvez accéder est restauré par l'interface de vos offres de classe statique. Statique n'est pas mauvais tant que votre application échoue toujours.

Une autre bonne alternative aux singletons est le modèle de monostate, où vous avez une classe qui implémente des champs statiques privés pour représenter le comportement "Singleton".

Voir:

Monostate
Monostate vs. Singleton

mise à jour: Cela m'aide souvent à garder un repos comme API à l'esprit, même pour les structures de programme internes. Avoir une classe qui est mise à jour de partout et envoie des avis à tout le monde est difficile de contrôler en ce qui concerne les conditions d'augmentation des conditions et des boucles d'infini (mise à jour -> Evénement -> Mise à jour -> ...)

Construire une interface de barre d'état (statique ou non) que vous pouvez accéder à l'endroit où vous en avez besoin. Grâce à une classe statique où vous avez accès à votre interface de la barre d'état ou par injection de dépendance si vous utilisez de telles techniques (non recommandées pour des projets plus petits). Chaque appel à votre interface de barre d'état doit être indépendant de tout événement pouvant être soulevé par la barre d'état pour éviter d'autres problèmes liés aux conditions d'augmentation. Pensez à l'interface de barre d'état comme un site Web pouvant être appelé à partir d'autres parties du programme pour pousser et tirer des informations.


5 commentaires

Donc, pour récapituler, vous ne voyez rien de mal avec notre concepteur actuel où le StatusBarManager est une classe statique? J'ai parcouru les autres liens que vous avez inclus. En ce qui concerne monostate, la question est que je ne veux pas que ce soit transparent. Tout le monde devrait savoir qu'il n'y a qu'une seule barre d'état et c'est ce qu'ils mettent à jour. C'est mon sentiment de toute façon. Mon problème principal avec les classes statiques et Singltons est la réutilisabilité des classes les référencées. Vous avez maintenant référence à une classe mondiale qui devrait être satisfaite si vous avez réutilisé la classe dans un autre projet.


Habituellement, la "mauvaise chose" sur la statique est. Lorsque vous avez de nombreuses classes dépendent de certaines classes statiques qui facilitent le refactoring et les tests impossibles. Si vous n'êtes pas votre barre d'état, mais votre interface dans la barre d'état est statique, la barre d'état peut toujours être échangée pour les cas de test. La classe statique sera suffisamment petite pour la réécrire au besoin.


Si vous souhaitez vous débarrasser de la classe statique, je ne vois aucune possibilité d'injection de dépendance (injection de propriété ou constructeur). L'injection de constructeur aura besoin de la barre d'état (ou de la barre d'état) dans chaque constructeur qui pourrait être trop. Latimérisme s'appuiera sur le fait que vous injectez la propriété. C'est généralement fait par un microkernel. L'ensemble du programme s'appuiera sur ce noyau. DI est un bon moyen si vous avez besoin de code testable, mais vous pouvez vous confondre dans des projets plus petits car il est plus difficile de déboguer.


Toute commentaires sur la suggestion d'avoir Mobilemain contient une référence statique une classe d'instance StatusBarManager? Certaines des classes qui mettent à jour la barre d'état sont également des singletons, comme notre communicationManager responsable de la mise à jour de l'état d'icônes de transmission chaque fois qu'il communique au serveur. Pour DI, Wiliterait-il à CommunicationManager, j'ai une propriété pour StatusBarmanager, puis à Mobilemain, j'aurais une commande comme CommunicationManager.statusbarmanager = _statusbarmanager, avec _statusbarmanager représentant désormais une instance du responsable appartenant à Mobilemain?


Au lieu de le lier statique du MobileMain, vous pouvez créer la fonction / la propriété de StatusBarManager Static. Que vous n'obtenez pas une dépendance supplémentaire et plus de responsabilités à votre mobilemain qui ne fera pas bien échouer. Quel avantage auriez-vous lorsque vous accédez à la barre d'état via StatutBarManager via Mobilemain? DI fonctionne comme si vous avez décrit mais est souvent mis en œuvre plus dynamiquement en utilisant des attributs et / ou des conteneurs dans lesquels vous enregistrez vos instances (comme barre d'état). Ensuite, le mobilemain configurera le conteneur comme: _Container.registersingleton ();



-1
votes

Il est difficile de donner des conseils sans savoir plus d'architecture de votre application, mais vous devriez peut-être envisager une injection de dépendance. Par exemple, passez une instance de barre d'état au constructeur de chaque classe qui l'utilise directement.


1 commentaires

Cela ressemble à une idée approximative. Maintenant, vous devez passer des paramètres supplémentaires dans tous vos objets au moment de la construction, ajouter du code supplémentaire dans vos constructeurs pour les initialiser, des champs supplémentaires dans des objets partout où stocker de nombreuses références à ce qui est en réalité un seul objet, et tous vos types. ne peut plus être compilé sans le type de barre d'état.



1
votes

Vous pouvez simplement utiliser le modèle code> observateur Ajoutez la barre d'état code> comme un auditeur à vos 20 objets. Cela éliminera les singletons et mieux suivre SRP et trempera, mais vous devrez déterminer si cela vaut la peine d'être effort. Un singleton peut être meilleur si l'indirection ajoute trop de complexité et d'injection de dépendance n'est pas possible.

public class StatusBar implements StatusListener {
}

public interface StatusListener {
   public statusChanged(String newStatus)
}


0 commentaires

2
votes

Avoir une classe de barre d'état ou une classe StatusBarManager ou non n'est pas une grosse affaire. Mais avoir de nombreuses classes dans votre application connaît sur StatusBars et StatusBarmanagers est une mauvaise idée, cela entraînera une forte couplage et une journée probablement de la douleur.

Comment?

Imaginez que les composants qui rapportent actuellement le statut à une barre d'état doivent être réutilisés dans une autre application. - Utilise une console de texte pour signaler le statut? - Statut des rapports à plusieurs endroits? ou - Ne signalez pas le statut du tout!

meilleure alternative: -La vie d'écoute. Exposez un événement modifié de statut sur votre classe (vous pouvez utiliser un rappel) ou peut-être sur une ressource partagée existante que vos classes ont en commun. D'autres parties, comme votre barre d'état, peuvent souscrire à l'événement. Et devrait se désabonner chaque fois que l'abonnement n'est plus nécessaire / valide, pour éviter les fuites, comme vous le mentionnez!

-Suite que vous avez marqué WPF, pour WPF, avoir une propriété de dépendance 'Stattext', peut sembler une autre option tentante, avec cette approche lorsque vous avez des propriétés de statut multiples, vous avez besoin d'une façon de déterminer lequel on raconte lequel Le statut le plus intéressant qui doit être affiché sur votre barre d'état maintenant! Ce qui pourrait être une liaison, multiples multiples (Blech, complexité) ou une propriété de dépendance modifiée le gestionnaire d'événements.

Cependant, je vous conseillerais de garder la dépendance et la dépendancePropertoires limitées autant que possible de votre calque d'interface utilisateur. La raison en est qu'ils s'appuient implicitement sur un répartiteur sur le fil de l'interface utilisateur, et ne peuvent donc pas être adaptés facilement pour les tâches non-UI.

Comme il existe de nombreuses parties de votre application, vous pouvez également trouver qu'il est raisonnable d'avoir une combinaison de ces deux, en utilisant un endroit et une autre.


3 commentaires

Merci d'avoir répondu. Je voulais clarifier ma compréhension de votre meilleure approche. Nous devrions placer un événement StatusChanged dans chaque classe qui met à jour la barre d'état. L'augmentation de cet événement qui aura la barre de statut qui l'abonne. Est-ce ce que vous suggérez? Si tel est le cas, la barre d'état ou StatusBarmanager doit avoir la connaissance de chaque classe à mettre à jour pour pouvoir s'abonner à l'événement StatusChanged. Je comprends la question avec toutes nos classes ayant une connaissance du statut-statut de réutilisation, qui fait partie de la raison pour laquelle je veux faire le changement.


J'ai également envisagé d'utiliser une notificationManager, qui peut relever votre suggestion d'une ressource partagée. Cela pourrait gérer toutes les notifications, y compris la barre d'état. Ce qui serait idéal, c'est avoir une interface, les classes pouvaient donc être réutilisées dans n'importe quel projet tant qu'ils avaient une classe qui a mis en œuvre l'interface de l'inotiernement, mais je ne pense pas que vous puissiez le faire avec un singleton ou une classe statique.


Ah - Il y a un bon point - la barre d'état n'a pas vraiment besoin de savoir sur chaque classe! Vous pouvez plutôt avoir une méthode Statusbar.updaTestatus (), puis dans une classe de couche supérieure (qui a une connaissance de tout pour les autres raisons de toute façon), faites-la de manière à établir tous les gestionnaires d'événements pour appeler cette méthode.



0
votes

Les classes dépendent implicitement sur n'importe quelle utilisation singleton et explicitement à tous les paramètres du constructeur. Je suggérerais d'ajouter une interface au singleton, de sorte que les méthodes nécessaires soient exposées aux classes à l'aide de la barre Istatus. C'est plus de code, mais facilitera les tests unitaires.


0 commentaires