如何在MVC模式中实现类之间的通信?

本文关键字:之间 通信 实现 MVC 模式 | 更新日期: 2023-09-27 18:12:51

前言:这个问题不是关于ASP的。. NET MVC框架。

Edit:更清楚的是,应用程序是用c#编写的游戏,所以各种web框架都不适用。


我应该如何最好地连接类与事件时,使用MVC模式构建的东西?

我想写一些MVC代码,这样我就可以更多地了解设计模式。我理解为什么模式的这三个元素应该分开,但是我不确定如何实现将它们连接在一起。我是用c#写这篇文章的,我也是一个新手,它让我想到应该使用事件。我主要不确定如何正确地订阅/取消订阅事件,我需要进行完整性检查。

例如,我将发布视图/控制器类。在本例中,视图希望发送一个DataRequest事件,控制器希望订阅该事件,以便将其传递给模型。另一方面,控制器会在某个时刻引发一个datauupdate事件,视图应该订阅这个事件。我实现它们相互订阅的方式有意义吗?

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

And the Controller:

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
    }
}

如何在MVC模式中实现类之间的通信?

你所做的和试图做的是MVP模式,而不是MVC。简而言之,MVC模式用于请求-响应架构,而不是事件驱动。流程为:

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

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

下面的例子只是一个说明,所以期望应用非现实生活中的逻辑。控制器的格式为:

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

UI会是这样的:

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

这个例子显示了对控制器的请求是在一个按钮点击事件中被发起的。

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

首先,您所描述的被称为模型-视图-表示器。到目前为止,我找到的最好的描述是Robert Martin的《c#中的敏捷原则、模式和实践》。

第二,你不需要MVP的事件。其思想是呈现者和视图相互引用,并且知道它们的接口,这样数据请求/更新就可以直接调用。

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

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

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

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

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

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