J'ai quelques classes comme indiqué ici ici ... p> Comment puis-je modifier J'essaie de mettre en œuvre les modèles d'usine où les sous-classes s'inscrivent avec l'usine, mais j'ai simplifié le code de cette question. P> p> TrueFalezVetion Code> classe de sorte que la méthode statique soit toujours exécutée pour que je reçois 1 au lieu de 0 quand je cours ma méthode principale? Je ne veux pas de changement dans la méthode principale. P>
4 Réponses :
Vous pouvez appeler:
Class.forName("yourpackage.TrueFalseQuestion");
Où puis-je appeler cette méthode? Chaque classe est dans un fichier différent.
Avant de réellement besoin du truefalentetion code> initialisateur à exécuter. Dans votre exemple - au début de la méthode principale
Y a-t-il quelque chose que je puisse y arriver sans changer quoi que ce soit dans la méthode principale, car cela créerait une sorte de dépendance de cette classe dans la méthode principale que je veux éviter.
Dans ce cas, vous n'avez pas de dépendance du temps compilé. Ce n'est qu'une dépendance du temps d'exécution. Selon la façon dont vous êtes "enregistrer" vos sous-classes, vous pouvez faire les chèques appropriés.
Y a-t-il un bon moyen de se débarrasser de la dépendance du temps d'exécution aussi?
@TP: Si vous pouviez énumérer toutes les classes dans un package, vous pouvez simplement interroger tous les noms de ceux de cette implémentation question code> et faire ceci. Depuis que cela ne peut pas être fait (voir ici: Stackoverflow.com/questions/520328/... ), vous êtes laissé avec examiner des pots à la main (UGH) ou en utilisant une sorte de fichier de configuration ...
@TP c'est exactement comme @martinho Fernandes dit
Pour enregistrer la classe Assurez-vous que La raison pour laquelle je ne pense pas faire de cela dans le truefalentetion code> avec l'usine, son initialisateur statique doit être appelé. Pour exécuter l'initialiseur statique de la classe Code> TrueFalentetion Code>, la classe doit être référencée ou doit être chargée par réflexion avant
questionfactory.map.size () code> est appelé. Si vous souhaitez quitter la méthode code> MAIN > intacte, vous devez la réfléchir ou le charger par réflexion dans le
InitializIzer STATIC CODE> STATIC. Je ne pense pas que ce soit une bonne idée, mais je vais juste répondre à votre question :) Si cela ne vous dérange pas du
QuestionFactory Code> Connaître toutes les classes qui implémentent
Question Code> Pour les construire, vous pouvez simplement les référer directement ou les charger par réflexion. Quelque chose comme:
La déclaration code> S est avant le bloc code> statique code>. Si vous ne voulez pas
QuestifFactory CODE> avoir une connaissance des implémentations de
Question Code>, vous devrez les énumérer dans un fichier de configuration qui est chargé par
QuestifFactory code>. La seule autre autre voie (éventuellement folle) que je pouvais penser à le faire, serait de regarder à travers tout la classe de classe pour les classes qui implémentent
question code> :) qui pourrait fonctionner mieux si toutes les classes qui ont mis en œuvre la question
code> devait appartenir au même paquet - Remarque: je n'entraîne pas cette solution;) p>
QuestionFactory Code> Initializer statique est parce que les classes comme
truefalentetion code> ont leur propre initialisateur statique qui appelle dans
questionnaire code>, qui à ce stade est un objet incomplètement construit, qui demande simplement des problèmes. Avoir un fichier de configuration qui répertorie simplement les classes que vous souhaitez
QuestionFactory Code> Pour savoir construire, puis les enregistrer dans son constructeur est une solution fine, mais cela signifie changer votre
Main code > Méthode. P> P>
Pour référence, cette conception est venue à éviter le besoin de l'usine de savoir sur les classes de questions (ici: Stackoverflow.com/Questtions/2582357/... ).
Je n'avais pas vu cette question. Quelque chose doit savoir sur les implémentations de l'interface de la question, qu'il s'agisse de l'usine directement ou d'une sorte de fichier de configuration. Comme je l'ai dit, le seul autre moyen est de passer à travers toutes les classes de la classe de classe et de voir s'ils mettent en œuvre la question. Notez également la mise en garde d'avoir une usine incomplètement construite dans ma réponse ci-dessus. Cela peut fonctionner maintenant, mais il n'y a aucune garantie sur l'état de l'objet à l'avenir (ni même dans le présent, à travers les plates-formes).
L'initialiseur statique pour la classe ne peut pas être exécuté si la classe n'est jamais chargée.
Vous devez donc charger toutes les classes appropriées (ce qui sera difficile, car vous ne les connaissez pas tous à la compilation. temps) ou se débarrasser de l'exigence de l'initialisateur statique. P>
Une façon de faire ce dernier est d'utiliser le ServiceLoader code>
. p>
avec le serveur code> vous simplement Mettez un fichier dans dans le Meta-Inf / Services / Package.Question CODE> et énumérez toutes les implémentations. Vous pouvez avoir plusieurs fichiers em> de tels fichiers, un fichier par .jar. De cette façon, vous pouvez facilement expédier des implémentations code> supplémentaires code> séparément de votre programme principal. P>
QuestionFactory code> Vous pouvez simplement utiliser
serviceLodaer.load (Question.Class) Code> Pour obtenir un
ServiceLoader CODE>, qui implémente
itérable
Pour exécuter les initialiseurs statiques, les classes doivent être chargées. Pour que cela se produise, votre classe "principale" doit dépendre (directement ou indirectement) sur les classes, soit directement ou indirectement les amener à être chargée de manière dynamique; par exemple. Utilisation de Je pense que vous essayez d'éviter les dépendances intégrées dans votre code source em>. Les dépendances statiques sont donc inacceptables et appelles à Cela vous laisse deux alternatives: p>
Écrivez du code désordonné pour itérer sur les noms de ressources dans certains packages, puis utilisez Créez un fichier (par exemple une ressource de classier) contenant une liste des noms de classe que vous souhaitez charger et écrire un code simple pour lire le fichier et utiliser classe.forname (...) code>. p>
class.forname (...) code> avec des noms de classe codée dur sont également inacceptables. P>
class.forname (...) code> pour charger ces ressources qui ressemblent à vos cours. Cette approche est délicate si vous avez une classe de classe compliquée, et impossible si votre parcours de classe effectif comprend un URLClassloader avec une URL distante (par exemple). P> LI>
class.forname (...) code> charger chacun. p> li>
ul>