2009-08-31 8 views
0

(Beaucoup édité) J'ai quelques classes avec des membres abstraits. Le type concret des membres abstraits doit être déterminé lors de l'instanciation de classe, en fonction de l'entrée de l'utilisateur. Cependant, le type concret du second membre peut dépendre du premier membre. J'essaye de faire quelque chose en gardant à l'esprit le modèle de conception MVP. J'ai enseigné comment faire en sorte que le Présentateur passe un délégué au Ctor du Modèle, qu'il utiliserait (le Ctor) pour demander les informations nécessaires à l'instanciation de la classe. Je ne suis pas sûr que ce soit une bonne idée. Voici ce que j'ai écrit:Utilisation du MVP pour un modèle d'objet structuré composite

// In the Model : 
public class Model 
{ 
    public E Element1; 
    public E Element2; 

    public Model(CustomCtor<ModelElement, IModelElement> GetModelElement) 
    { 
     this.Element1 = (E)GetModelElement(ModelElement.E, null); 
     this.Element2 = (E)GetModelElement(ModelElement.E, null); 
     //Element2 does not depend on Element1 in this case though. 
    } 
} 

public abstract class E : IModelElement { } 

public class EA : E 
{ 
    public string Element1; 
    public EA(string Element1) { this.Element1 = Element1; } 
} 

public class EB : E 
{ 
    public int Element1; 
    public EB(int Element1) { this.Element1 = Element1; } 
} 

public interface IModelElement { } 

public enum ModelElement { E, EA, EB } 

// In the Presenter : 
public class Presenter 
{ 
    View.View view1; 

    public Presenter() { } 
    public void SetView(View.View view) { this.view1 = view; } 

    public Model.Model MakeModel() 
    { 
     CustomCtor<ModelElement, IModelElement> GetModelElement = new CustomCtor<ModelElement, IModelElement>(GetModelElement<ModelElement, IModelElement>); 
     return new Model.Model(GetModelElement); 
    } 

    private Model.IModelElement GetModelElement<ModelElement, Tout>(Model.ModelElement ME, object obj) 
    { 
     switch (ME) 
     { 
      case Model.ModelElement.E: 
       return MakeE(); 
      // One case per Model.ModelElement 
      default: 
       throw new Exception("ModelElement not implemented in the Presenter."); 
     } 
     return default(Model.IModelElement); 
    } 

    private E MakeE() 
    { 
     switch (view1.AskEType()) 
     { 
      case 1: 
       return MakeEA(); 
      case 2: 
       return MakeEB(); 
      default: 
       throw new Exception(); 
     } 
    } 

    private EA MakeEA() { return new EA(view1.AskString("EA.Element1 (String)")); } 
    private EB MakeEB() { return new EB(view1.AskInt("EB.Element1 (Int)")); } 
} 

// Shared to the Model and the Presenter : 
public delegate TOut CustomCtor<EnumType, TOut>(EnumType Enum, object Params) where EnumType : struct; 

// In the View : 
public class View 
{ 
    public int AskEType() 
    { 
     Console.WriteLine(string.Format("Type of E : EA(1) or EB(2)?")); 
     return int.Parse(Console.ReadLine()); 
    } 
    public string AskString(string Name) 
    { 
     Console.Write(string.Format("{0} ? ", Name)); 
     return Console.ReadLine(); 
    } 
    public int AskInt(string Name) 
    { 
     Console.Write(string.Format("{0} ? ", Name)); 
     return int.Parse(Console.ReadLine()); 
    } 
} 

//In the Program : 
class Program 
{ 
    static void Main(string[] args) 
    { 
     View.View view1 = new View.View(); 
     Presenter.Presenter presenter1 = new Presenter.Presenter(); 

     presenter1.SetView(view1); 
     presenter1.MakeModel(); 
    } 
} 

Est-ce logique? Y a-t-il un nom pour la chose que j'essaie de faire? (à côté de "Une chose étrange") Etes-vous au courant d'un modèle de conception que je devrais lire? J'ai enseigné le mélange du motif de conception Builder avec le MVP, mais je ne suis pas sûr de savoir comment je ferais cela.

Merci

Répondre

1

Je ne suis pas certain que c'est ce que votre demande au sujet, mais je suppose que vous essayez de garder votre point de vue isolé à partir de votre modèle. Si c'est effectivement ce que vous essayez de faire, je pense que vous adoptez une approche beaucoup trop compliquée. La vue est simplement un moyen de présentation et de feedback. Il n'a vraiment pas besoin de savoir quoi que ce soit sur les modèles, il peut être conçu pour utiliser des données simples dans un sac de propriété quelconque. Cela crée une séparation plus nette, cependant, il rend souvent les données de rendu et le maintien de la vue beaucoup plus difficile aussi bien.

La première question que je voudrais poser est, est-ce vraiment la peine de dépenser autant d'efforts en gardant votre vue entièrement isolée de votre modèle? Que gagnez-vous vraiment en ayant une séparation absolue?

Si vous avez effectivement besoin d'une séparation, assurez-vous de bien comprendre les rôles de vue et de présentateur. La vue est bête ... elle ne sait rien et ne fait rien. Il présente des informations et des formulaires. Le navigateur émet des commandes demandées par l'utilisateur. Le présentateur gère les commandes et dirige les données vers leur vue. Le concept de "présentateur demandant la vue" pour n'importe quoi est généralement incorrect. Le présentateur doit gérer directement la commande (requête http), il doit donc connaître tous les détails concernant une commande particulière. Au moment de rendre la vue, le présentateur doit fournir toutes les données à la vue, quelle que soit la forme dans laquelle la vue doit apparaître. Si vous ne souhaitez pas que votre vue soit connue de votre modèle d'objet, créez des propriétés dans la vue. lui-même pour contenir les données ou créer un modèle spécifique à la vue qui encapsule les données requises.

EDIT:

Je viens de lire votre mise à jour. Je pense que je comprends un peu mieux votre problème maintenant. Tout d'abord, avant d'aller plus loin, il faut réorganiser un peu les responsabilités. Actuellement, vous l'avez tel que votre vue est responsable de la gestion des entrées. C'est un peu une corruption du but et du concept d'une «vue». Dans les deux MVP et MVC, la vue est supposée être aussi "stupide" que possible, et ne devrait pas être responsable du traitement de quoi que ce soit ... commandes, actions, entrées, etc. devraient tous être la responsabilité du contrôleur ou du présentateur. Voyant que votre vue est en fait une application de console, pas une application de formulaires Web (ce qui était mon hypothèse initiale), je pense que MVC pourrait être mieux adapté à vos besoins. MVP est une bonne solution pour contourner les lacunes d'ASP.NET WebForms, mais elle n'est pas aussi puissante ou réussie pour aider à résoudre des problèmes distincts que MVC. Je voudrais examiner l'implémentation d'un modèle MVC, qui a été conçu à l'origine pour les applications de type console. Le contrôleur devient le gestionnaire d'entrée central, qui envoie ensuite des commandes aux gestionnaires de commandes et à votre modèle. La vue serait alors pure et vraie pour former ... seulement l'information de rendu et rien d'autre.

S'il y a une raison pour laquelle vous ne pouvez pas utiliser une approche MVC, ce qui serait idéal et que vous devez utiliser MVP, je peux vous donner plus de conseils sur la façon dont vous pourriez résoudre votre implémentation actuelle. Cependant, je vous suggère fortement d'utiliser MVC, car ces patterns ont été conçus à l'origine pour résoudre le problème que vous essayez de résoudre ... dans les applications console.

+0

J'ai écrit ce code avec la visionneuse étant une console, mais en fait je prévois d'utiliser un "IView" parce que les vues réelles seront WinForm et WebForm. De plus, les entrées seront un peu plus complexes (dropdown et zone de texte numérique principalement) donc j'ai prévu de faire des contrôles utilisateur pour chaque type de composant. J'ai également prévu de faire en sorte que le Présentateur lise les informations directement à partir de la vue (et ne rende pas les valeurs de retour de la vue). Compte tenu de cette information supplémentaire, pourriez-vous quand même me suggérer d'aller avec le MVC au lieu du MCP? Merci pour votre contribution, c'est vraiment apprécié. – Tipx

+0

Avec WebForms, MVP peut être utile. Il est difficile de créer un MVC pour WebForms tel qu'il est. Un MVP peut également fonctionner avec Windows Forms, car WinForms et WebForms fonctionnent de manière très similaire. Cependant, cela ne change pas vraiment l'image. Il est très important que la vue soit "bête" et que le présentateur gère les entrées. Le présentateur ne devrait jamais avoir à demander à la vue pour quoi que ce soit ... comme l'entrée doit d'abord être acheminée par le présentateur, et non l'inverse. Une implémentation IView devrait donner au présentateur la possibilité de pousser les données vers la vue, mais pas grand-chose d'autre. – jrista

+0

Merci, je vais garder cela à l'esprit pendant que je vais essayer certaines choses. J'ai une formation inégalée en programmation et je n'ai pas vu beaucoup de modèles de design, mais je ne doute pas que vos conseils m'épargneront des pièges! (même ainsi, je ferai des erreurs, mais j'apprendrai d'eux.) Merci. – Tipx

Questions connexes