8
votes

Modèle pour construire une grande hiérarchie d'objets

J'ai un problème qui implique une hiérarchie d'objets relativement importante comme suit:

  • jeu a un gestionnaire communautaire
  • Gestionnaire communautaire a un réseau
  • réseau a beaucoup de joueurs
  • réseau a beaucoup amitié
  • joueur a un gestionnaire de stratégie
  • joueur a une mémoire
  • joueur a un quartier
  • Quartier a beaucoup de joueurs
  • Gestionnaire de stratégie a beaucoup de stratégies

    Comme vous pouvez le constater, la hiérarchie est relativement complexe et dans au moins un endroit cyclique (réseau comporte de nombreux agents ayant un quartier qui possède un réseau). Pour le moment, j'utilise une méthode de construction statique sur un GameFactory classe pour construire toute la hiérarchie, mais je suis sûr que c'est la façon la moins flexible de le faire!

    En termes de construction d'une hiérarchie complexe d'objets Quel est le meilleur modèle à utiliser? J'ai lu sur la méthode usine , abstrait usine et Builder motifs et je pense que l'un des motifs d'usine convient mais je ne peux pas t vraiment savoir comment l'appliquer à une hiérarchie aussi complexe?

    Comme je le vois, j'aurai besoin de nombreuses usines pour chaque partie du système, mais cela entraînera une collection de classes d'usine reflétant les classes de modèle.


    EDIT: Il est devenu évident de la discussion des suggestions données jusqu'à présent que j'aurais dû expliquer davantage pourquoi j'ai besoin d'usines pour construire mes hiérarchies d'objets plutôt que de permettre aux constructeurs eux-mêmes de construire leurs dépendances.

    C'est parce que j'utilise une injection de dépendance pour aider au développement axé sur les tests. Je prends une approche ma moqueuse pour les tests nécessitant la possibilité d'injecter des simulacres représentant des dépendances d'un objet et, en tant que tel, je dois éviter d'utiliser nouveau dans tous les constructeurs.

    des suggestions données jusqu'à présent, il semble qu'il y ait un certain nombre de moyens possibles de faire cela:

    • Créez un constructeur secondaire dans chaque classe qui construit toutes les dépendances requises par l'objet en cours de construction. Cela permet une injection de dépendance et une construction de hiérarchie d'objet simple.
    • Demandez à une classe d'usine (une seule ou une hiérarchie d'eux en fonction du type de motif usine utilisé) de mappage à chaque classe de domaine pour faire face à sa construction.
    • Utilisez une combinaison de ces méthodes où les classes d'usine ne sont créées que lorsqu'il existe quelque chose qui varie dans le processus de construction (c'est-à-dire que différentes sous-classes doivent être construites dans certaines circonstances)

      Je suis enclin à prendre le dernier itinéraire. Quel est le consensus sur la meilleure approche pour prendre cette situation?


      EDIT: Je révoque la réponse actuelle (celle de Patrick Karcher) depuis maintenant que cette question a été clarifiée, aucune des suggestions ne sont complètes.


1 commentaires

Serait préférable de poser une nouvelle question (référencer celui-ci), pour plus de clarté.


3 Réponses :


2
votes

si rien ne varie , c'est-à-dire. Si votre processus de construction est corrigé, je recommanderais le moyen le plus simple: les objets eux-mêmes s'occupent de construire leurs objets dépendants et d'établir des liens (potentiellement bidirectionnels).

Exemple: Pour un objet parent avec une collection d'enfants, le parent peut avoir une méthode AddChild garantissant la cohérence de la relation bidirectionnelle:

  1. Obtenez le parent précédent de l'enfant; Si ce n'est pas nul, retirez l'enfant de cet ancien parent.
  2. Changer le champ des parents à l'enfant au nouveau parent
  3. Ajoutez l'enfant à la collection d'enfants du nouveau parent.

    Si quelque chose varie , comme des sous-classes que doivent être utilisées dans un contexte, vous devez définir exactement ce qui varie. Ce n'est qu'après avoir trouvé votre besoin précis, les modèles correct peuvent apparaître. : -)

    Nous pourrions aider avec la dernière partie, mais vous êtes le seul qui peut donner les informations requises ...; -)


2 commentaires

Comme il vient de dire à Patrick, j'exige en fait une injection de dépendance, raison pour laquelle je prenais la route d'usine. Désolé, j'aurais dû faire cela clair dans mon post initial. Séparez de ce que certaines des classes de domaine varient, en particulier des joueurs. Chaque joueur a une méthode de choix d'un résultat dans le jeu et j'ai actuellement une hiérarchie des classes de joueurs. Cela signifie-t-il que je devrais avoir une usine pour gérer des joueurs générant et laisser un constructeur gérer les autres entités? Je ne sais pas non plus où l'injection de dépendance convient ici ...


@toby ok. Pensez-vous que vous mettrez à jour votre question avec cette requis, de donner un contexte aux lecteurs et d'expliquer pourquoi une solution est choisie?



4
votes

Il est important de comprendre pourquoi vous avez besoin d'une usine. Comme pour beaucoup de "bonnes" pratiques, une usine peut générer certains avantages, que vous parfois veux et que vous obtenez seulement en les utilisant correctement.

Souvent l'usine est une autre classe dans votre modèle d'objet. Par exemple, vous vous retrouverez souvent avec un joueur parce que vous avez un quartier avec une collection lecteurs et vous itération à travers elle, faire des choses aux joueurs. Ou vous commencez par un objet . Ou (je devine) Vous avez déjà un joueur vous obtenez un amitié et vous obtenez le lecteur de celui-ci. Donc, un amitié est l'usine pour lecteur objets et un lecteur est usine pour amitié objets!

Vous faites parfois des raisons pour NO-Domaine, des objets usine dédiés . Vous pourriez avoir une classe d'usine comme point de départ pour des objets que vous allez commencer votre logique. Souvent, ils sont utilisés quand il y a beaucoup de façons difficiles, certains de vos objets doivent être instanciés et l'usine est un bon moyen de les organiser. Parfois, vos objets doivent être instanciés, par exemple, une couche de données et un utilisateur et un contexte, et une usine peut conserver ces choses, rendre vos objets et vous éviter de devoir vous répéter dans de nombreux constructeurs différents. Parfois, l'usine peut générer automatiquement des références communes que vos différents outils ont besoin.

Il y a une utilisation d'une usine qui se développe rapidement en popularité et mérite une mention spéciale. Il s'agit de l'utilisation d'une classe d'usine pour ajouter une couche de mauvaisedirection à injecter des dépendances , en particulier pour test unitaire .

mon conseil est si vous n'avez pas de raison spécifique d'utiliser un objet d'usine à l'esprit, ne vous inquiétez pas pour eux. Il suffit de construire vos objets avec de bons constructeurs. Ensuite, il sera naturel d'ajouter des propriétés qui renvoient des objets liés; Ce seront vos premières usines. Cela pourrait être un bon exemple de la façon dont vous ne voulez pas vous soucier des modèles de conception au début; Les modèles de conception ne fournissent pas de succès. Tu fais. Les modèles, comme les différents modèles d'usine, peuvent aider mais ne doivent pas remplacer la pensée de base orientée objet.

Avez-vous des raisons spécifiques à l'esprit pour pourquoi vous avez besoin d'objets d'usine dédiés?


3 commentaires

Je ne pensais pas que c'était lié avant, mais j'utilise une injection de dépendance tout au long de la hiérarchie des modèles, car j'essaie d'utiliser le comportement axé sur le développement avec une approche ma moqueuse. Injecter les moqueurs exige que la dépendance injecte aussi loin que je comprenne. Je suppose que la question est de savoir s'il faut avoir deux constructeurs, un pour l'injection de dépendance et une autre pour que l'objet construit ses propres dépendances ou d'utiliser une usine pour générer et fournir les dépendances. Est la première une approche commune? Je suis plus enclin à ce dernier.


Chaque option que vous mentionnez une cabine sera bien utilisée. Je préfère les constructeurs et plus loin quand je peux avoir un constructeur (ou si plusieurs constructeurs, la dépendance est injectée de la même manière.) La plupart de mes objets sont fabriqués par des "usines" (qui sont généralement d'autres objets métier) que Construisez et renvoyez ces objets à l'aide du constructeur, mais le constructeur rend l'objet autonome. Cela a l'avantage substantiel d'aider les classes à être véritablement noires.


Dans mon projet actuel, toutes mes classes qui effectuent l'accès aux données sont construites avec un objet de données. La page crée-la automatiquement pour moi et la place à mon objet de contexte utilisateur, qui est le point de départ de la plupart de mes autres objets. Dans une page entière, je ne l'injecterai souvent jamais moi-même, car j'ai une grande chaîne d'objets créant d'autres objets. L'injection est un peu agréable dans la production (it Bools Connections gentiment) mais en testant c'est génial. Et parce que dans le constructeur, même s'il est généralement fabriqué de toute façon, j'ai terminé le contrôle le niveau d'unité . Je l'aime bien.



2
votes

Kle a raison de manipuler différemment en fonction de la statique des relations. J'ajouterais qu'il est typique des classes d'usine pour refléter le modèle d'objet. Un moyen facile de penser à eux comme objet intelligent qui connaît comment pour connecter les différentes classes de votre modèle.


2 commentaires

Est-ce quelque chose que quelque chose fait généralement si - il semble assez gonflé d'avoir une hiérarchie de classe d'usine pour chaque classe de domaine?


C'est assez courant. L'alternative est que les objets ont plus d'intelligence qui provoque ensuite une sorte de blague différente. Le meilleur exemple s'attend à ce que l'objet de cercle sache de se peindre. Il amène rapidement des cours à responsables de toutes les interactions telles que la sérialisation ou la morphing. Ce code nain rapidement l'objectif initial de la classe. Mieux concentrer ce comportement dans des classes distinctes. À la fin, en utilisant des usines et similaires sont un outil pour vous aider à maintenir vos codes le niveau d'accouplement et de cohésion souhaité.