2

序言:这个问题与 ASP.NET MVC 框架无关。

编辑:更清楚地说,该应用程序是用 C# 编写的游戏,因此各种 Web 框架都不适用。


在使用 MVC 模式构建东西时,我应该如何最好地将类与事件联系起来?

我想写一些 MVC 代码,这样我就可以了解更多关于设计模式的信息。我理解为什么模式的这三个元素中的每一个都应该是分开的,但我不确定如何实现将它们连接在一起。我正在用 C# 编写这个,我也是新手,我觉得应该使用事件。我主要不确定我应该如何正确订阅/取消订阅事件,我需要进行健全性检查。

例如,我将发布 View/Controller 类。在这个例子中,视图想要发送一个 DataRequest 事件,而控制器想要订阅它以便将它传递给模型。另一方面,控制器会在某些时候引发视图应该订阅的 DataUpdated 事件。我实现它们相互订阅的方式是否有意义?

////////////////////////////////////////////////////
public class UIScreenView
{
    public event System.EventHandler<System.EventArgs> DataRequestedEvent;

    //====================================
    private void DataUpdatedEventHandler(object sender, System.EventArgs args);


    //====================================
    //====================================
    public void Subscribe(UIScreenController controller)
    {
        controller.DataUpdatedEvent += DataUpdatedEventHandler;
        controller.Subscribe(this);
    }

    //====================================
    //====================================
    public void UnSubscribe(UIScreenController controller)
    {
        controller.DataUpdatedEvent -= DataUpdatedEventHandler;
        controller.UnSubscribe(this);
    }
}

和控制器:

public class UIScreenController
{
    private UIScreenView view;

    public event System.EventHandler<System.EventArgs> DataUpdatedEvent;

    private void DataRequestedEventHandler(object sender, System.EventArgs args);

    public void Init(UIScreenView v)
    {
        view = v;

        if (view != null)
        {
            view.Subscribe(this);
        }
    }

    ~UIScreenController()
    {
        if (view)
        {
            view.UnSubscribe(this);
            view = null;    
        }
    }

    public void Subscribe(UIScreenView view)
    {
        view.DataRequestedEvent += DataRequestedEventHandler;
    }

    public void UnSubscribe(UIScreenView view)
    {
        view.DataRequestedEvent -= DataRequestedEventHandler;
    }

    private void DataRequestedEventHandler(object sender, System.EventArgs args)
    {
        //request data from model
    }
}
4

3 回答 3

2

首先,您所描述的称为模型-视图-演示者。到目前为止,我发现的最好的描述是在 Robert Martin 的“敏捷原则、模式和 c# 实践”中。

其次,MVP 不需要事件。这个想法是演示者和视图相互引用并知道它们的接口,以便直接调用数据请求/更新。

第三,对于没有经验的开发人员来说,这种模式可能很麻烦。好处是视图可以替换为假视图,因此您可以轻松地对演示者进行单元测试。但是,如果这是您从 oop 开始的,那么将视图和演示者合并到一个类中的贫血方法可能会更简单。

于 2013-05-10T17:49:30.697 回答
2

您所做并尝试制作的是 MVP 模式,而不是 MVC。简而言之,MVC 模式用于请求-响应架构,而不是事件驱动。流程是:

  • UI 执行请求
  • 控制器接受请求
  • 控制器处理请求(如访问模型等)
  • 控制器将响应发送到 UI

如果你想在 C# 中实现它,我假设是 winform,那么你的请求将在事件中处理。假设在您的游戏中,您选择菜单加载游戏,然后需要显示保存的游戏数据。

以下示例只是一个说明,因此请期待非现实生活中的逻辑适用。控制器将如下所示:

public class SaveDataController
{
    public SaveData[] GetSaveData()
    {
        return Model.GetSaveData();
    }
}

用户界面将如下所示:

public void LoadGameButton_Click(object sender, EventArgs e)
{
    SaveDataController controller = new SaveDataController();
    SaveData[] saveData = controller.GetSaveData();
    SaveDataList.DataSource = saveData;
}

此示例显示对控制器的请求是在按钮单击事件中启动的。

正如其他人已经说过的,MVC 架构不适合非 Web 应用程序(或事件驱动),因为它不处理事件方法。大多数 UI 逻辑将在事件中处理。

于 2013-05-13T13:52:10.213 回答
1

你有点搞反了。MVC(与 WebForms 之类的东西相比)的主要教训之一是 Web 应用程序中没有任何“事件”。您所拥有的只是 HTTP 规范,它将客户端和服务器之间的事务定义为 GET/POST(不太常见的是 PUT/DELETE)。MVC 中没有“按钮单击”之类的东西。相反,您有一个来自页面上的表单的 HTTP POST。

此外,每个 HTTP 请求都与之前的请求完全断开连接,并且没有真正的好方法来保持客户端和服务器之间的连接打开。服务器真正能做的就是接受请求,然后呈现适当的响应。所有试图混淆这种不连贯的现实的尝试都导致了更弱的 Web 框架,而不是更好的框架。

各种 MVC 框架主要执行所谓的“模型绑定”。HTTP POST 或 GET 不带有从类构造的“对象”;它真正拥有的只是 POST 或 GET 变量和标题等。MVC 世界的模型绑定器基本上采用这些简单的参数,并根据预期的类类型应该是什么(通常在控制器中定义,或按照约定)动态地从它们构造对象。然后,控制器允许您基于这些对象执行代码操作,并最终以视图的形式发送回响应。

与其在这一点上用自己的框架重新发明轮子,不如选择 1-2 个流行的 MVC 框架并学习它们的范例。我碰巧在 ASP.NET MVC 中工作并且喜欢它,但是 Ruby on Rails 非常擅长。每种主要语言可能都有 1-2 个成熟、可靠的 MVC 框架,因此您可能应该从使用您熟悉的语言的框架开始。

在您熟悉了现有的 MVC 框架之后,您可以开始考虑如何以不同的方式实现它,如果这是您最终想要的。

于 2013-05-10T13:30:42.090 回答