“MVC”中的“控制器”中有什么?

2022-08-31 06:21:26

我想我理解了MVC的基本概念 - 模型包含应用程序的数据和行为,视图负责向用户显示它,控制器处理用户输入。我不确定的是控制器中到底有什么

例如,假设我有一个相当简单的应用程序(我特别想到Java,但我认为相同的原则也适用于其他地方)。我将代码组织成 3 个名为 、 和 的包。app.modelapp.viewapp.controller

在包中,我有几个类反映了应用程序的实际行为。这些并使用和触发视图以在适当时更新。app.modelextends ObservablesetChanged()notifyObservers()

该包具有一个类(或用于不同类型的显示的多个类),该类使用组件来处理显示。其中一些组件需要反馈到模型中。如果我理解正确,视图不应该与反馈有任何关系 - 这应该由控制器处理。app.viewjavax.swing

那么我实际上在控制器中放了什么呢?我是否只需调用控制器中的方法即可将 放在视图中?如果是这样,是否应该在控制器中进行任何验证等?如果是这样,我如何将错误消息反馈回视图 - 应该再次通过模型,还是控制器应该直接将其发送回视图?public void actionPerformed(ActionEvent e)

如果在视图中完成验证,我应该在控制器中放入什么?

很抱歉这个长问题,我只是想记录我对这个过程的理解,希望有人能为我澄清这个问题!


答案 1

在你建议的例子中,你是对的:界面中的“用户点击了'删除此项目'按钮”,基本上应该只调用控制器的“删除”功能。但是,控制器不知道视图的外观,因此您的视图必须收集一些信息,例如“单击了哪个项目?

在对话表单中:

查看:“嘿,控制器,用户刚刚告诉我他希望删除第4项。
控制器:“嗯,检查了他的凭据后,他被允许这样做......嘿,模特,我希望你得到第4项,并尽你所能删除它。
模型:“项目 4...明白了。它已被删除。回到你身边,控制器。
控制器:“在这里,我将收集新的数据集。回到你身边,看看。
查看:“很酷,我现在将向用户显示新集。

在该部分的末尾,您有一个选项:视图可以发出单独的请求,“给我最新的数据集”,因此更纯净,或者控制器通过“删除”操作隐式返回新数据集。


答案 2

问题在于,人们认为视图、控制器和模型必须尽可能彼此独立。它们不会 - 视图和控制器经常交织在一起 - 将其视为 .MVCM(VC)

控制器是用户界面的输入机制,它经常纠缠在视图中,特别是对于GUI。然而,视图是输出,控制器是输入。视图通常可以在没有相应控制器的情况下工作,但是如果没有视图,控制器通常不太有用。用户友好的控制器使用视图以更有意义,更直观的方式解释用户的输入。这就是它很难将控制器概念与视图分开的原因。

将密封盒中检测场上的无线电控制机器人视为模型。

该模型完全是关于状态和状态转换的,没有输出(显示)的概念或触发状态转换的内容。我可以得到机器人在场上的位置,机器人知道如何转换位置(向前/向后/向左/向右迈出一步。无需视图或控制器即可轻松设想,但没有任何用处

想象一个没有控制器的视图,例如,网络上另一个房间中另一个房间中的某人看着机器人的位置,因为(x,y)坐标沿着滚动控制台流式传输。这个视图只是显示模型的状态,但这个家伙没有控制器。同样,在没有控制器的情况下很容易想象这个视图。

想象一个没有视图的控制器,例如,有人被锁在壁橱里,无线电控制器调谐到机器人的频率。该控制器正在发送输入并导致状态转换,而不知道它们正在对模型执行什么(如果有的话)。易于想象,但如果没有来自视图的某种反馈,就没有真正有用。

大多数用户友好的UI将视图与控制器协调,以提供更直观的用户界面。例如,想象一个带有触摸屏的视图/控制器,以2D形式显示机器人的当前位置,并允许用户触摸屏幕上恰好位于机器人前面的点。控制器需要有关视图的详细信息,例如视口的位置和比例,以及相对于机器人在屏幕上的像素位置触摸的点的像素位置)才能正确解释这一点(与用无线电控制器锁定在壁橱中的家伙不同)。

我回答了你的问题了吗?:-)

控制器是从用户获取用于使模型进入转换状态的任何内容。尝试将视图和控制器分开,但要意识到它们通常相互依赖,因此如果它们之间的边界模糊是可以的,即将视图和控制器作为单独的包可能不会像您希望的那样干净地分开,但这没关系。您可能必须接受控制器不会与视图完全分离,因为视图与模型分离。

...是否应该在控制器中进行任何验证等?如果是这样,我如何将错误消息反馈回视图 - 应该再次通过模型,还是控制器应该直接将其发送回视图?

如果在视图中完成验证,我应该在控制器中放入什么?

我说链接的视图和控制器应该自由交互,而无需通过模型。控制器接受用户的输入,并应进行验证(可能使用来自模型和/或视图中的信息),但如果验证失败,控制器应该能够直接更新其相关视图(例如错误消息)。

对此的严峻考验是问自己,由于其他人的验证错误(例如,壁橱里的家伙试图告诉机器人离开场地),一个独立的视图(即在另一个房间通过网络监视机器人位置的人)是否应该看到任何东西。通常,答案是否定的 - 验证错误阻止了状态转换。如果没有状态转换(机器人没有移动),则无需告诉其他视图。壁橱里的家伙只是没有得到任何反馈,他试图导致非法过渡(没有视图 - 糟糕的用户界面),也没有其他人需要知道这一点。

如果那个拿着触摸屏的人试图把机器人送离场,他会得到一条很好的用户友好信息,要求他不要通过将其从检测场上发送出去来杀死机器人,但同样,没有其他人需要知道这一点。

如果其他视图确实需要了解这些错误,那么您实际上是在说,来自用户的输入和任何由此产生的错误都是模型的一部分,整个事情有点复杂......


推荐