四人帮设计模式如何融入MVC范例?

20

我已经思考了一段时间关于设计模式,并且我现在才开始看到如何在我的开发工作中有意识地应用它们。然而,我仍然对书的开头关于MVC的论述以及它与书的其他内容的关系感到困惑。

我使用过的大多数框架——Spring、Yii、ASP.NET,甚至Objective-C Cocoa(UIKit)——都支持MVC范式。我理解MVC是因为对我来说它是一种有用的分类对象及其之间消息或交互方式的方法。此外,即使您不打算以MVC的方式进行思考,这些框架也会强制您采用该范例。

我也觉得我理解了设计模式的前提:它们真的不喜欢子类化,他们喜欢抽象接口,他们努力实现松耦合。我不能说我完全理解所有的模式以及它们的用途,但我正在逐渐领会。

我的问题是:MVC和设计模式之间的相互作用是什么?他们在书的第一章关于MVC应用程序示例中表达的意思是什么?在MVC范式中,某些设计模式是否不相关?例如,我想知道Command模式应该如何适用于MVC。它似乎非常有用,但我们是否创建一个 CommandModelCommandController来发送给其他控制器?还是只需按照书中的建议创建一个Command对象?基本上,我想知道MVC和设计模式的思想是否完全不相关,而我只是不理解,还是是否存在某些模式不适合这种范例。


1
这可能是一篇不错的阅读材料:https://dev59.com/b07Sa4cB1Zd3GeqP6cMY - roman
我认为第一部分(实际上是第二章)的重点是展示这些是真正应用于实际程序中的概念,而不仅仅是象牙塔里空洞理论的又一学术作品。 - tcarvin
4个回答

15

我个人的看法是MVC是观察者模式的简化版本,而观察者模式又是中介者模式的简化版本。

MVC:一个模型,一个视图,控制器管理它们之间的通信。

观察者模式:一个模型,多个视图(观察者/订阅者),发布者管理它们之间的通信。

中介者模式:多个不同的模型,多个视图,中介者管理它们之间的通信。


1
我看到了你对这个问题的深刻见解,我完全同意。 - Miroslav Trninic
我认为在MVC中,模型和视图之间并不存在一对一的关系。同一个模型可以很容易地拥有多个视图。至少在我的理解中,这是使用MVC的优势之一;即使用多个表示同时更新同一个模型的单个更新。 - Thomas Eizinger
@ThomasEizinger 但是在这种情况下,您会看到什么区别(如果有的话)与观察者模式? - Stephane Rolland
大概每个人都同意模型-视图部分是100%的观察者模式(如果你只做WebApp开发,可能会更难理解,因为你只有一个视图)。我认为控制器部分大多类似于命令模式(控制器就是你的命令)。在用户界面上,您单击按钮,然后执行某些命令。当然,您可以找到大约5种其他具有某些相似性的模式,但从概念上讲,它是最接近的项目。 - Vitalii Fedoryshyn
@StephaneRolland 下一个回答是错误的(需要提到它,因为答案被标记为已接受):
  1. 在MVC模式中可以有多个视图(请参见维基百科,了解其最初的介绍)。
  2. 我完全不同意中介者模式的使用,它用于其他目的,只需阅读GoF书籍的维基百科定义并查看当前模式的UML图即可。
  3. “控制器管理它们之间的通信”-拜托,这是错误的说法。
- Vitalii Fedoryshyn
显示剩余2条评论

9
在GoF书中提到的MVC是针对桌面应用程序的,它使用观察者模式来更新视图。而GoF书中的命令示例是针对编辑器的。
还有其他类型的MVC,其中使用其他设计模式可能不那么明显:
MVC和MVVM之间有什么区别?
Presentation abstraction control GoF书中说:

表面上看,这个例子反映了一种将视图与模型分离的设计。但是这种设计适用于一个更普遍的问题:解耦对象,使得对其中一个对象所做的更改可以影响到任意数量的其他对象,而不需要更改的对象知道其他对象的详细信息。Observer (第293页) 设计模式描述了这种更普遍的设计。

MVC的另一个特点是视图可以嵌套。例如,按钮控制面板可以作为包含嵌套按钮视图的复杂视图来实现。对象检查器的用户界面可以由嵌套视图组成,这些视图可以在调试器中重复使用。MVC使用CompositeView类支持嵌套视图,它是View的一个子类。CompositeView对象的行为就像View对象一样;复合视图可以在可以使用视图的任何地方使用,但它还包含并管理嵌套视图。

同样,我们可以认为这是一种让我们像处理其组件之一一样处理复合视图的设计。但是这种设计适用于一个更普遍的问题,即每当我们想要将对象分组并像单个对象一样处理该组时,都会出现这种问题。Composite (163) 设计模式描述了这种更普遍的设计。它允许您创建一个类层次结构,其中某些子类定义原始对象(例如Button),而其他类定义复合对象(CompositeView),将原始对象组装成更复杂的对象。

MVC还允许您更改视图对用户输入的响应方式,而无需更改其视觉呈现方式。例如,您可能希望更改它对键盘的响应方式,或者让它使用弹出菜单而不是命令键。MVC在Controller对象中封装了响应机制。有控制器的类层次结构,使得创建一个新控制器作为现有控制器的变体变得容易。

视图使用Controller子类的实例来实现特定的响应策略;要实现不同的策略,只需用不同类型的控制器替换实例即可。甚至可以在运行时更改视图的控制器,以便让视图更改其对用户输入的响应方式。例如,可以通过给视图提供忽略输入事件的控制器来禁用视图,使其无法接受输入。

View-Controller关系是Strategy (315) 设计模式的一个例子。Strategy是表示算法的对象。当您想要静态或动态地替换算法、有大量算法变体或算法具有您想要封装的复杂数据结构时,它非常有用。

MVC使用其他设计模式,例如Factory Method (107)来指定视图的默认控制器类和Decorator (175)来向视图添加滚动条。但MVC中的主要关系由Observer、Composite和Strategy设计模式给出。


4
MVC是一种模式。但它只涵盖了Web应用程序的一个小方面。另一个常见的与MVC一起使用的模式是Repository。这些是更大型的架构模式...它们的范围对整个项目有更大的影响。
GOF模式会在各个地方以微小的方式介绍自己。根据设计选择,它们可以帮助构建MVC基础设施。例如,策略经常被使用,因此您可以插入不同的方法来执行诸如“身份验证”等操作。
您不必按原样使用这些模式,甚至不必使用完全相同的代码结构。更多的是您在设计中采用模式的设计原则/目标。

2

MVC是一种架构模式。它非常适合与其他设计模式(如命令模式)配合使用。但是,您不应该仅仅因为某些模式存在并被写在权威书籍中就去应用它们。当您遇到编程/设计问题并且有人已经发现了解决这个问题的方法并将其写下来时,您才应该应用模式。解决问题的方法就是模式。例如,您有一个应用程序将数据保存到数据库中。要保存的数据非常复杂:必须插入一些记录,更新一些记录和删除一些记录。步骤的顺序很重要,因为要插入到一个表中的记录取决于要插入到另一个表中的记录。因此,必须使用数据库事务。实现事务的一种可能的方式是使用命令模式。在Larman的“应用UML和模式”一书中非常好地解释了如何实现它(第556页,章节“使用模式设计持久性框架”,部分“使用命令模式设计事务”)。在那里,PersistentObject是一个抽象的Model类,所有其他Model类都继承自它。在该示例中,MVC实现在UI、应用程序和域层中,而Command则实现在持久性层中。这些模式有助于解决不同的问题,并且它们在该示例中相互支持。

点赞,因为你明确说明了MVC实际上是一种架构模式。 - raddevus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接