将MVP用于复合结构化对象模型

时间:2009-08-31 18:49:35

标签: c# mvp composite

(编辑很多)我有一些Abstracts成员的课程。抽象成员的具体类型将根据用户的输入在类实例中确定。但是,第二个成员的具体类型可能取决于第一个成员。

我正在努力做一些保持MVP设计模式的事情。我教过如何让Presenter将代理传递给模型的Ctor,他(Ctor)将用它来请求类的实例化所需的信息。我不确定这是不是一个好主意。这是我写的:

// 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();
    }
}

这有意义吗?我正在尝试做的事情是否有名称? (旁边的“怪异的东西”) 你知道我应该阅读的设计模式吗? 我教过将Builder设计模式与MVP混合,但我不确定我是怎么做的。

由于

1 个答案:

答案 0 :(得分:1)

我不确定这是你的要求,但我假设你试图让你的观点与你的模型隔离开来。如果这确实是你想要做的,我认为你采取了一个太复杂的方法。视图只是一种演示和反馈媒介。它实际上不需要了解模型的任何信息,它可以设计为在某种属性包中使用简单数据。这样可以创建更清晰的分离,但是,它通常会使渲染数据和维护视图变得更加困难。

我要问的第一个问题是,真的值得花费这么多努力来保持你的观点与你的模型完全隔离吗?通过绝对分离你真正获得了什么?

如果确实需要分离,请确保您了解视图和演示者的角色。这种观点是愚蠢的......它什么都不知道,什么都不做。它提供信息和表格。浏览器发出用户请求的命令。演示者处理命令,并将数据定向到其视图。 “演示者询问视图”的概念通常是不正确的。演示者应该直接处理命令(http请求),因此它应该知道有关特定命令的任何和所有细节。当呈现视图时,演示者应该以视图需要的任何形式向视图提供任何数据。如果您不希望视图知道对象模型,则在视图上创建属性本身包含数据,或创建封装所需数据的视图特定模型。

编辑:

我刚看了你的更新。我想我现在明白了你的问题。首先,在我走得更远之前,你需要稍微重新组织一下职责。目前,您拥有它以使您的视图负责处理输入。这有点歪曲了“观点”的目的和概念。在MVP和MVC中,视图应该尽可能“愚蠢”,并且实际上不应该负责处理任何事情......命令,动作,输入等都应该由Controller或Presenter负责。

看到您的视图实际上是一个控制台应用程序,而不是Web表单应用程序(这是我最初的假设),我认为MVC实际上可能更适合您的需求。 MVP是解决ASP.NET WebForms缺陷的一个很好的解决方案,但它不像MVC那样有助于解决单独的问题。我将研究实现MVC模式,该模式最初是为控制台类型应用程序设计的。控制器成为中央输入处理程序,然后向命令处理程序和模型发出命令。然后,视图将是纯粹的,真实的......只能呈现信息,而不是其他任何内容。

如果有一些原因你不能使用我认为理想的MVC方法,并且必须使用MVP,我可以提供更多关于如何修复当前实现的建议。但是,我强烈建议使用MVC,因为这些模式最初是为了解决你试图在控制台应用程序中解决的问题而设计的。