11
votes

Est-ce que classe.Newinstance () suive le modèle de conception "abstrait"?

J'ai commencé à lire "Java efficace" de Joshua Bloch (deuxième édition). Pendant la lecture de l'élément 2 ( considérer un constructeur face à de nombreux paramètres de constructeur ), il existe une déclaration particulière que l'auteur fait w.R.t la méthode CLASS.NEWInStance () . Plus précisément, l'auteur dit que

La mise en œuvre traditionnelle de l'usine abstraite en Java a été l'objet "Classe", avec la méthode "NewInstance" jouant la partie de la méthode "Build".

Cette partie m'a confondue un peu - ma compréhension du modèle de conception de l'usine abstraite est qu'elle est utilisée pour représenter une usine d'usines. La méthode classe.Newinstance () , à mon avis, borde davantage sur la philosophie de codage "statique de l'usine" (qui a d'autre choix, est l'élément 1 du même livre)

pensées, n'importe qui? Je me préparais fort pour craquer quelques entretiens difficiles et j'apprécierais vraiment que mes principes fondamentaux soient solides avant de comparaître pour de telles entretiens.

merci.


0 commentaires

3 Réponses :


1
votes

À mon avis, il se réfère au code tel que le texte suivant: xxx

classe est l'usine abstraite. Il est devenu concret lorsque vous avez passé le paramètre type, par exemple. entier . Vous avez ensuite appelé le "Builder", NewInstance () .


1 commentaires

Logique. J'attendrai un moment avant d'accepter votre réponse, juste pour voir ce que les autres pensent à cela.



3
votes

Je ne pense pas que rien suggère que l'usine abstraite est "une usine d'usine". Un abstractFactory ne crée pas d'usines qui créent t s, il crée t s directement.

L'idée qu'il est abstrait est de permettre à la logique de créer t à injecter. Donc, par exemple, vous pourriez avoir: xxx

dans ce cas, ConnecFactory crée Connection S, mais est abstraite parce que C'est une interface.

J'ai tendance à être d'accord avec vous que classe . NewInstance () est pas un exemple canonique d'une usine abstraite, car Classe est pas résumé et, en fait, il ne peut pas être étendu . Vous ne pouvez pas demander un Classe et avoir une implémentation initiale à initialiser la nouvelle valeur à 1 , et une autre initialisation de la nouvelle valeur à 7 .

Vous pouvez cependant étirer des choses en disant quelque chose comme classe est une usine abstraite de INPUTREAM S, avec des implémentations concrètes Classe et Classe . Ce n'est pas la signification traditionnelle de "abstrait" si (il n'y a toujours qu'une classe: classe ).

mais même il est inutile comme une usine abstraite, parce que la façon dont vous avez Mettre en place une nouvelle la version de "l'usine" consiste à créer une nouvelle classe qui étend introuvable . Ce n'est guère quelles usines abstraites sont destinées à.


3 commentaires

Eh bien, techniquement, vous pouvez appeler integer.class.getconstructor (int.class) .Newinstance (1); , mais il n'est guère pratique.


@Duncan: Vous pouvez, mais cela n'a rien à voir avec l'usine abstraite. Le point d'abstrait est que la méthode que vous appelez est spécifiée par l'interface. C'est le contraire: vous avez une usine de béton avec plusieurs méthodes d'usine appelées différentes manières.


+ 1 pour l'exemple d'explication et d'injection.



6
votes

Voici mon avis.

Tout d'abord, le modèle d'usine abstrait n'est pas destiné à être une usine d'usines. L'aspect clé de ce modèle est qu'il existe une interface accessible avec une implémentation d'usine sous-jacente (probablement inaccessible) à travers laquelle vous pouvez obtenir des interfaces accessibles d'implémentations d'objets (probablement inaccessibles). Je sais que c'est un long jeu méchant de la façon dont je comprends certaines des conditions d'applicabilité de ce modèle dans le livre de gamma:

  • Un système doit être indépendant de la manière dont ses produits sont créés, composés et représentés
  • Vous souhaitez fournir une bibliothèque de produits de classe et vous souhaitez révéler uniquement leurs interfaces, pas leurs implémentations.

    À la fin, vous obtenez des objets, pas des usines.

    Deuxièmement, je ne ferais pas 1: 1 relations entre les concepts de modèle et les mots-clés de la langue. "Abstract Factory" ne traduit pas nécessairement toujours sur la classe Java Classe abstraite ou constructions. Vous pouvez toujours avoir une classe instanciable régulière, extensible et instanciable qui représente une "usine abstraite" tant que vous garantissez en quelque sorte que le code client est indépendant de l'usine sous-jacente et des implémentations d'objet. Ceci est le cas de java.lang.class , qui n'est pas abstrait ni une interface, mais le travail à cacher la mise en oeuvre du constructeur sans paramètre du type qu'il représente via le NewInstance () < / code> méthode. Il est probablement plus clair si vous l'utilisez comme: xxx

    classe lit "abstrait usine" et objet joue le "Produit abstrait" à la mise en œuvre du type.

    dernier, NewInstance () n'est pas une méthode d'usine statique, je pense parce que ce modèle est destiné à renvoyer des instances de la classe, elle est mise en œuvre. NewInstance () ne renvoie pas les instances de Classe ni sous- classe es. Il renvoie des instances du type qu'il représente. Il n'est pas non plus une "méthode d'usine", tout comme Bloch états dans son livre.


3 commentaires

Bingo! C'est ce que je cherchais. Merci pour l'explication détaillée.


[classe] fait le travail de masquer la mise en œuvre du constructeur sans paramètre du type qu'il représente. Je suis complètement en désaccord, NewInstance () Nothing. Pour appeler directement le constructeur, vous devez savoir qu'un constructeur visible non-ARG existe. Pour instancier en utilisant NewInstance () , vous devez savoir qu'un constructeur non-ARG, visible existe. Le comportement de NewInstance () est bien spécifié, de sorte que c'est vraiment ne peut pas encapsuler quelque chose de conséquence. Et dans aucun cas, vous devez être conscient de la mise en œuvre réelle du constructeur lui-même.


Mark, je suis d'accord avec votre déclaration selon laquelle classe.newinstance () ne cache rien, c'est-à-dire que l'appelant de cette méthode doit s'assurer qu'un constructeur de no-arg correspond à l'instance de classe spécifiée. Appliquer la même ligne de pensée au modèle d'usine, si un client obtient une référence à une implémentation d'usine (par exemple, par injection) et invoque une méthode à ce sujet, ne devrait-il pas être sûr que l'instance d'usine injectée ne s'applique pas simplement Toutes les méthodes d'interface d'usine pour lancer un non supposé ? À mon avis, c'est rarement quelque chose Vraiment transparent.