Je le doute depuis longtemps ... espoir quelqu'un peut me illuminera.
Supposons que j'ai 3 classes dans mon modèle. P>
class MyController { public View handleSomething() { Document document = myService.getDocument(); return document.getView(); } }
9 Réponses :
Peut-être que vous pourriez avoir quelque chose comme greveView () code> dans le document code>, le remplacer dans chaque implémentation? p>
salut! Toutes mes excuses pour -1, mais cela n'est pas bien conseillé. Un "modèle" représente les données commerciales [parfois nous obtenons des paresseux et ajoutons aussi une logique commerciale: s]. Cependant, le modèle ne sait pas comment il devrait être présenté. Considérez une application «utilisateur final» vs une application «admin». Les deux applications peuvent exploiter le même niveau d'entreprise et le même modèle, mais chacun peut souhaiter une vue différente [admin peut avoir plus de données]. La sélection de la vue d'intégration dans le modèle contraindre la même vision des deux applications. À moins que vous n'ayez mis en œuvre une substitution, rendant la méthode moot. De manière générale, le modèle devrait être présentatif-agnostique.
Votre contrôleur ne devrait pas em> savoir. Il devrait demander au document code> code> à s'afficher, et le document Imaginez-le si plus tard Stade Vous ajoutez un nouveau document code> type code> (dire, Peut-être que cela peut le faire autonome. E.g. p> code> peut le faire ou fournir suffisamment d'informations pour laisser la vue de la vue polymorphique.
tableur code>). Vous voulez vraiment seulement ajouter l'objet code> tablier code> (hériter de
document code>) et que tout fonctionne. Par conséquent, la feuille de calcul code> doit fournir la capacité de s'afficher. P>
new Spreadsheet().display(view);
@Brian agnew - J'aime cette réponse, mais je pense que les gens empêchent les gens de la manière d'accomplir cela. Même si vous indiquez Nouvelle feuille de calcul (). Affichage (); Code> Je garantis que les gens interrogent à quel point ressemble à ... les gens vont-ils se retrouver avec le type de test de code (chaqueObject). Si vous allez un peu plus en profondeur sur l'affichage, je vais +1 vous. :)
Étendez votre service pour renvoyer le type de document:
public interface ViewHandler { public getView(Document doc) } public class EmailViewHandler implements ViewHandler { public View getView(Document doc){ if(doc instanceof Email){ // return a view for the e-mail type } return null; // this handler cannot handle this type } }
La question concerne une bonne pratique de programmation orientée objet. Votre réponse utilise une approche procédurale et non une approche orientée objet. Le problème est que l'approche procédurale ne s'améliore pas bien car le "code client" est fortement couplé à la mise en œuvre actuelle du "code de la bibliothèque".
J'ai réalisé que. J'espère que ma réponse actuelle convient mieux à la question.
Bien sûr - mais si vous avez besoin de tests de type, je serais enclin à les mettre dans la classe d'usine. Vous pouvez probablement faire mieux que cela en enregistrant le gestionnaire contre la classe d'affichage.
Je ne suis pas sûr, mais vous pouvez essayer d'ajouter une classe d'usine basée sur des fonctions qui remplissent et supposé renvoyer une vue en fonction du type de document. Par exemple:
Le modèle "usine" est le meilleur moyen que je pense. Il devrait être dans le package "commun", où sont aussi vos interfaces. +1
Je ne pense pas que cela fonctionnera. Pour appeler la méthode ViewFactory.geview (), vous avez besoin d'une référence du type approprié (lettre ou email), mais le service renvoie un document, nous laissant le problème initial. Merci!
Je pensais que ce service renvoie un objet de type spécifique, qui a été lancé vers le document. Ai-je tort?
Oui, le service renvoie un document
Oui, selon la signature, ceci est un document. Et je pense que cela dépose un type approprié comme un email ou une lettre.
Oui mais au moins en Java, la correspondance de paramètres d'un appel de méthode est effectuée à l'heure de la compilation. Ainsi, avec une référence de document, vous ne pouvez pas appeler grevView (lettre d) ni greview (e-mail D)
C'est une excellente question. Il y a plus d'une approche plausible ici; Vous devez équilibrer les compromis et faire un choix qui convient à votre situation. P>
(1) Certains diront que cette interface de document devrait fournir une méthode d'instances de se rendre. Ceci est attrayant d'un point de vue OO, mais en fonction de vos technologies de vue, il peut être impraticable ou carrément laid de charger vos classes de documents concrètes - qui sont probablement simples classes de modèles de domaine - avec une connaissance des JSP, des composants balançoires ou autre. p>
(2) Certains suggéreront de mettre peut-être un (3) Malgré ces points, il est préférable que votre classe de contrôleur ne soit pas em> savoir quels types de documents existent dans l'univers et qui tapent chaque instance de J'irais au n ° 3 ou - si mon budget (à temps) pour travailler sur ce problème est petit - je (4) CODE SIZE-CODE Certaines connaissances de base du document code> > Types de mon contrôleur (comme vous dites que vous faites maintenant) en vue de passer à N ° 3 à l'avenir la prochaine fois que je suis obligé de mettre à jour mon contrôleur en raison de caractéristiques de OO Moins que optimales. Le fait est que les # 1-3 prennent chacun plus longtemps et sont plus complexes que n ° 4, même si elles sont "plus correctes". Coller avec # 4 est également un signe de tête au Yagni Principal : Il n'y a aucune certitude que vous ne serez jamais Découvrez les effets négatifs du n ° 4, a-t-il de sens de payer le coût de les éviter à l'avant? P> string greveViewName () code> méthode sur
document code> qui retourne, par exemple, le chemin d'accès à un fichier JSP pouvant accéder correctement à ce que Type de document. Cela évite la laideur du n ° 1 à un niveau (dépendances de la bibliothèque / code «levage lourd»), mais conceptuellement pose le même problème: votre modèle de domaine sait qu'il est rendu par JSPS et elle connaît la structure de votre webApp. P >
document code> appartient à. Envisagez de configurer une sorte de mappage de visualisation dans une sorte de fichier basé sur un texte: .properties ou .xml. Utilisez-vous le printemps? Spring DI peut vous aider à spécifier rapidement une carte de classes de documents concrètes et des composants JSP / View qui les rendent, puis transmettez-le à un constructeur / constructeur de votre classe de contrôleur. Cette approche permet à la fois: (1) votre code de contrôleur de rester agnostique de
type code> types et (2) votre modèle de domaine pour rester simple et agnostique des technologies de visualisation. Il vient au coût de la configuration incrémentielle: .properties ou .xml. P>
J'ai vu ce "modèle" plusieurs fois dans mon travail et j'ai vu de nombreuses approches pour le résoudre. Au point, je suggérerais
créer un nouveau service Mise en œuvre code> iviewselector code>, soit par des mappages de code papier, soit par configuration, et en lance Ceci effectue le mappage que vous avez besoin lorsque vous facilitant la séparation de la préoccupation [SOC] P> comme exemple d'utilisation, considérez les suivants p> < Pré> xxx pré> p> iviewselector code> p> li>
notsupportedexception code> chaque fois qu'une demande invalide est faite. P> LI>
ol>
+1 pour la théorie mais la mise en œuvre peut être considérablement améliorée. En utilisant des génériques, vous devriez être capable d'éliminer les références à des objets et à une vérification / coulée de type explicite.
Le modèle de visiteur peut fonctionner ici: Le visiteur est l'un des motifs les plus controversés, bien qu'il existe un certain nombre de variantes qui tentent de surmonter les limitations du modèle d'origine. P> Il serait plus facile de mettre en œuvre si la méthode acceptée (...) pourrait être mise en œuvre dans le document, mais le modèle s'appuie sur le type statique du paramètre "Ceci", donc je ne pense pas que cela soit possible dans Java - Vous devez vous répéter dans ce cas car le type statique de "ceci" dépend de la classe qui détient la mise en œuvre. p> si le nombre de types de documents est relativement petit et peu susceptible de croître, et le nombre de Les types de vue sont plus susceptibles de croître, alors cela fonctionnerait. Sinon, je chercherais une approche qui utilise une troisième classe pour coordonner l'affichage et essayer de conserver la vue et de documenter indépendants. Cette deuxième approche pourrait ressembler à ceci: p> Le but de l'affichage est d'associer des instances de document (ou des types de documents si un seul document d'un type donné peut être ouvert) avec Afficher les instances (ou afficher des types si une seule vue d'un type donné peut être ouverte). Si un document peut avoir plusieurs vues associées, la mise en œuvre de ViewManager ressemblerait à ceci à la place: P> class ViewManager {
public void display(Document document) {
List<View> views = getAssociatedViews(document);
for (View view : views) {
view.display();
}
}
protected List<View> getAssociatedViews(Document document) { ... }
}
premier off, la réponse des testaments Drews est absolument géniale - je suis nouveau ici et je n'ai pas la réputation de voter à ce sujet, sinon je le ferais.
Malheureusement, et cela peut être le mien Manque d'expérience, je ne vois aucune façon que vous allez éviter de compromettre une séparation de la préoccupation. Quelque chose va devoir savoir quel type de vision de créer pour un document donné - il n'y a aucun moyen de cela. P>
Comme Drew a souligné au point n ° 3, vous pourriez aller avec une sorte d'externe Configuration qui indiquerait à votre système sur lequel la classe d'affichage à utiliser pour quel type de document. Le point 4 de Drew est également un moyen décent d'aller, car même s'il casse le principe ouvert / fermé (je crois que c'est celui que je pense), si vous n'aurez qu'une poignée de sous-types de documents, il ne vaut probablement pas vraiment la peine de se prémonter avec. p>
Pour une variation de ce dernier point, si vous souhaitez éviter d'utiliser des chèques de type, vous pouvez implémenter une classe / méthode d'usine qui s'appuie sur une carte du document Sub. Types Pour afficher les instances: P>
public final class DocumentViewFactory { private final Map<Class<?>, View> viewMap = new HashMap<Class<?>, View>(); private void addView(final Class<?> docClass, final View docView) { this.viewMap.put(docClass, docView); } private void initializeViews() { this.addView(Email.class, new EmailView()); this.addView(Letter.class, new LetterView()); } public View getView(Document doc) { if (this.viewMap.containsKey(doc.getClass()) { return this.viewMap.get(doc.getClass()); } return null; } }
juste le faire!
// document.jsp <c:import url="render-${document.class.simpleName}.jsp"/>
@MAURICIO Comme indiqué ci-dessus, il peut produire soit le rendu-e-mail.jsp ou le rendu-lettre.jsp