模型视图控制器(MVC)一个相当实用且十分流行的设计模式。作为一位称职码农,你不可能没听说过吧。 不幸的是它难以让人理解。 在本文中,我将给出我认为是MVC的最简单的解释,以及为什么你应该使用它。

什么是模型 - 视图 - 控制器(MVC)?

在一个典型应用中,你会发现这三个基本组成部分:

  • 数据(模型)
  • 查看和修改数据的接口(视图)
  • 可以对数据施加的操作(控制器)

MVC模式,简言之,就是:

  1. 模型代表数据,除此之外别无它用。 模型不依赖于控制器或视图。

  2. 视图显示模型数据,发送用户动作(例如按钮点击)到控制器。 视图可以:

    • 独立于模型和控制器的; 或者

    • 作为控制器,因此依赖于模型。

  3. 控制器提供模型数据至视图,解释用户的行为,如按钮的点击。 控制器依赖于视图和模型。 在一些情况下,控制器和视图可以合二为一。

规则1是MVC的黄金法则,我再重复一遍:

模型代表数据,除此之外别无它用。 模型不依赖于控制器或视图。

以一个地址簿应用程序为例。 模型是一些Person对象,视图是一个GUI窗口,显示联系人列表,并且控制器处理用户行为诸如“删除联系人”,“添加联系人”,“发邮件至联系人”等。下面的例子没有使用MVC,因为模型依赖于视图。

//Example 1:
void Person::setPicture(Picture pict){
m_picture = pict; //set the member variable
m_listView->reloadData(); //update the view
}

下面的示例使用了MVC:

//Example 2:
void Person::setPicture(Picture pict){
m_picture = pict; //set the member variable
} void PersonListController::changePictureAtIndex(Picture newPict, int personIndex){
m_personList[personIndex].setPicture(newPict); //modify the model
m_listView->reloadData(); //update the view
}

在上面的例子中, Person类并不知道视图的存在。 PersonListController负责模型修改和视图更新。视图窗口告诉控制器用户的行为(就上述情况而言,它将提醒控制器用户修改了一个联系人的照片)。

MVC的优势在哪里?

不必要的复杂性是软件开发的梦魇。 它导致软件漏洞百出,维护费用昂贵。而到处引入依赖很容易就会造成代码过于复杂。 相反地,如果我们移除不必要的依赖可以改善代码质量,维护上更容易,因为代码可重复使用而无需修改。 你可以安心地复用旧的、稳定的代码不用顾虑招致新的bug。

MVC设计模式的主要优点是:

MVC使得模型类不加修改即可重复使用。

控制器存在的目的是消除模型与视图依赖关系。 从模型中移除视图依赖后,模型代码变得整洁起来。

为什么模型代码能这么小清新? 让我们继续以地址簿应用为例。 项目经理找到码农们,对他们说 ”我很欣赏联系人列表窗口,但我们需要另一个窗口显示所有联系人的照片,这些照片应该是处于一个表格布局中,每排五张照片。”

如果应用程序采用了MVC,这个任务相当简单。 目前主要有三个类: Person , PersonListControllerPersonListView。 还需要创建两个类: PersonPhotoGridViewPersonPhotoGridController 。 在Person类保持不变的情况下,很容易插入两种不同的视图。 怎么样啊!

如果应用程序具有例1中类似的结构,任务立马变得棘手了。此时有两个类Person 和PersonListView 。Person类不能插入另一种视图,因为它包含了涉及PersonListView类的具体代码 。 开发人员必须修改Person类以适应新的PersonPhotoGridView ,并最终像这样复杂化模型:

//Example 3:
void Person::setPicture(Picture pict){
m_picture = pict; //set the member variable
if(m_listView){ //check if it's in a list view
m_listView->reloadData(); //update the list view
}
if(m_gridView){ //check if it's in a grid view
m_gridView->reloadData(); //update the grid view
}
}

如你所观察到的一样,模型代码开始变得苦涩。 如果项目经理接着发话:“我们正在移植的应用程序到一个使用不同的GUI库的平台”,简洁性此时尤为突出。 采用MVC的Person类可以通过不同的GUI工具包显示无需任何修改。 单单创建一个控制器,并用新的库中的视图,就像你用旧的库一样。 如果没有MVC,支持多种GUI工具包将是一场噩梦。 最终代码可能会这样的:

//Example 4:
void Person::setPicture(Picture pict){
m_picture = pict;
#ifdef ORIGINAL_GUI_TOOLKIT
if(m_listView){ //check if it's in a list view
m_listView->reloadData(); //update the list view
}
if(m_gridView){ //check if it's in a grid view
m_gridView->reloadData(); //update the grid view
}
#endif
#ifdef NEW_GUI_TOOLKIT
if(m_listView){ //check if it's in a list view
m_listView->redisplayData(); //update the list view
}
if(m_gridView){ //check if it's in a grid view
m_gridView->redisplayData(); //update the grid view
}
#endif
}

setPicture方法基本上会乱上一团。

为什么不把控制器代码置入视图?

一直解决例4中的尴尬代码的方案是将控制器代码从模型移动到视图,像这样:

//Example 5:
PersonListView::newPictureClicked(Picture clickedPicture){
m_selectedPerson.setPicture(clickedPicture);
this->reloadData();
}

上述例子也可使模型易于复用,这是MVC的主要优势。 当视图将只显示一种类型的模型对象,合并视图和控制器是比较合适的。 例如,一个SinglePersonView将只显示一个Person的对象,所以SinglePersonView可兼作控制器。

然而,如果控制器与视图分离,MVC有第二个优点:

MVC可以使视图可重复使用的而无需修改。

MVC模型不仅使得模型简洁,视图同样如此。 理想情况下,列表视图应该能够显示的任何列表,不只是Person的对象。 例5中的代码不能是一个通用的列表视图,因为它与模型耦合在一起(Person类)。要想视图(如列表视图,或表格视图)和模型代码同时可重复使用,MVC是唯一的选择。 控制器移除模型和视图间的依赖关系,这使得它们在其他地方可以被复用。

结论

MVC设计模式在视图和模型间插入控制器类,移除视图和模型间的依赖。 模型以及视图,可重复使用而无需修改。 这样,实现新的功能和维护变得轻而易举。 该用户很快得到稳定的软件,该公司节省了资金,而且开发人员不发疯。 这样好不?

翻译来源:http://www.tomdalling.com/blog/software-design/model-view-controller-explained/

模型 - 视图 - 控制器(MVC)详解的更多相关文章

  1. 模型-视图-控制器 (MVC)

    在MVC中 ,模型代表数据和业务规则, 视图包含了用户界面元素,例如文本,表单等 控制器则管理模型和视图中的通信

  2. 学习模型-视图-控制器MVC模式

    1.MVC简介 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分 ...

  3. 模型-视图-控制器的C++解释

    模型-视图-控制器 (MVC) 并非一种技术,而是软件设计/工程的一个概念.MVC包含三个组成部分,如下图所示 模型 模型直接响应对数据的处理,比如数据库.模型不应依赖其它组成部分,即视图或控制器,换 ...

  4. 模型-视图-控制器模式(MVC模式,10种常见体系架构模式之一)

    一.简介: 架构模式是一个通用的.可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题.架构模式与软件设计模式类似,但具有更广泛的范围. 模型-视图-控制器模式,也称为MVC模式.是软件 ...

  5. 设计模式-结构型模式, mvc 模型视图控制器模式(8)

    MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式.这种模式用于应用程序的分层开发. Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO.它 ...

  6. [框架模式]经典的模型视图控制器模式MVC

    参考:<设计模式> http://blog.csdn.net/u010168160/article/details/43150049 百度百科 引言: Model(模型)是应用程序中用于处 ...

  7. MVC详解(转)

    原文链接:MVC详解 MVC与模板概念的理解 MVC(Model View Controller)模型-视图-控制器   MVC本来是存在于Deskt op程序中的,M是指数据模型,V是指用户界面,C ...

  8. 设计模式 --- 模型-视图-控制器(Model View Controller)

    模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程 ...

  9. MODEL-View-Controller,既模型-视图-控制器

    Swing组件采用MVC(MODEL-View-Controller,既模型-视图-控制器)设计模式,其中模型(Model)用于维护组件的各种状态,视图(View)是组件的可视化表现,控制器(Cont ...

随机推荐

  1. sort函数的例子

    10.11编写程序,使用stable_sort和isShorter将传递给你的elimDups版本的vector排序.打印vector的内容. #include<algorithm> #i ...

  2. 通用的 makefile 小工具分享 - Easymake 使用说明

    Easymake 使用说明 介绍 Easymake 是一个在linux系统中 C/C++ 开发的通用 makefile.在一个简单的 C/C++ 程序中使用 easymake,你甚至可以不写一行 ma ...

  3. java.util.Stack类简介

    Stack是一个后进先出(last in first out,LIFO)的堆栈,在Vector类的基础上扩展5个方法而来 Deque(双端队列)比起Stack具有更好的完整性和一致性,应该被优先使用 ...

  4. Java内存模型浅析

    JVM在执行java程序时会将它所管理的内存划分成若干个不同的数据区域.如图所示: 其中方法区和堆是所有线程共享的数据区,其他区域则是线程隔离的数据区. 这些区域的功能各有不同: 程序计数器:可以理解 ...

  5. YII设置用户访问过滤

    设置用户访问过滤 1.哪个控制器设置访问过滤,就在哪个控制器中添加如下代码 class XxxController extends Controller { //当前控制器是否使用过滤功能 publi ...

  6. Android 70道面试题汇总

    1. 下列哪些语句关于内存回收的说明是正确的? (b) A. 程序员必须创建一个线程来释放内存 B. 内存回收程序负责释放无用内存 C. 内存回收程序允许程序员直接释放内存 D. 内存回收程序可以在指 ...

  7. 20160331javaweb 之JSP page 指令

  8. Force removing ActivityRecord,app died, no saved state报错的理解

    为什么说理解呢?出现这个问题,我的情景是,在activity里面直接起了一个Thread,线程里面进行了一个繁重的任务,当线程执行完后,这个activity也销毁了,界面显示的任务栈下面的一个活动.百 ...

  9. 配置git DiffMerge工具

    git的命令行貌似没有特别好用的UI工具,不管是Android Studio自带的还是其他的,完全代替命令行好像做不到.再加上对git来说没什么比diff和merge更正常不过的事情了.那就配置命令行 ...

  10. 对比iOS中的四种数据存储

    来自于大牛的文章给大家分享下 :http://www.infoq.com/cn/articles/data-storage-in-ios/