0

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

我正在尝试做一些事情来牢记 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 混合,但我不确定我会如何做到这一点。

谢谢

4

1 回答 1

1

我不确定这是您要问的问题,但我假设您正试图使您的视图与模型隔离。如果这确实是您想要做的,我认为您采取的方法过于复杂。视图只是一种演示和反馈媒介。它真的不需要知道任何关于模型的知识,它可以被设计成利用某种属性包中的简单数据。这创建了更清晰的分离,但是,它通常也使渲染数据和维护视图变得更加困难。

我要问的第一个问题是,花这么多精力让视图与模型完全隔离真的值得吗?通过绝对分离,你真正获得了什么?

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

编辑:

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

看到您的视图实际上是控制台应用程序,而不是 Web 表单应用程序(这是我最初的假设),我认为 MVC 实际上可能更适合您的需求。MVP 是解决 ASP.NET WebForms 缺陷的一个很好的解决方案,但它在帮助分离关注点方面不如 MVC 强大或成功。我会考虑实现一个 MVC 模式,它最初是为控制台类型的应用程序设计的。控制器成为中央输入处理程序,然后向命令处理程序和您的模型发出命令。然后视图将是纯粹的和真实的形式......仅呈现信息而没有其他内容。

如果出于某种原因您不能使用 MVC 方法,我认为这将是理想的,并且必须使用 MVP,我可以就如何修复当前实现提供更多建议。但是,我强烈建议考虑使用 MVC,因为该模式最初旨在解决您试图解决的问题......在控制台应用程序中。

于 2009-08-31T19:09:37.177 回答