模型 - 视图 - 控制器(MVC)详解
模型视图控制器(MVC)一个相当实用且十分流行的设计模式。作为一位称职码农,你不可能没听说过吧。 不幸的是它难以让人理解。 在本文中,我将给出我认为是MVC的最简单的解释,以及为什么你应该使用它。
什么是模型 - 视图 - 控制器(MVC)?
在一个典型应用中,你会发现这三个基本组成部分:
- 数据(模型)
- 查看和修改数据的接口(视图)
- 可以对数据施加的操作(控制器)
MVC模式,简言之,就是:
模型代表数据,除此之外别无它用。 模型不依赖于控制器或视图。
视图显示模型数据,发送用户动作(例如按钮点击)到控制器。 视图可以:
独立于模型和控制器的; 或者
作为控制器,因此依赖于模型。
控制器提供模型数据至视图,解释用户的行为,如按钮的点击。 控制器依赖于视图和模型。 在一些情况下,控制器和视图可以合二为一。
规则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 , PersonListController和PersonListView。 还需要创建两个类: PersonPhotoGridView和PersonPhotoGridController 。 在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)详解的更多相关文章
- 模型-视图-控制器 (MVC)
在MVC中 ,模型代表数据和业务规则, 视图包含了用户界面元素,例如文本,表单等 控制器则管理模型和视图中的通信
- 学习模型-视图-控制器MVC模式
1.MVC简介 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分 ...
- 模型-视图-控制器的C++解释
模型-视图-控制器 (MVC) 并非一种技术,而是软件设计/工程的一个概念.MVC包含三个组成部分,如下图所示 模型 模型直接响应对数据的处理,比如数据库.模型不应依赖其它组成部分,即视图或控制器,换 ...
- 模型-视图-控制器模式(MVC模式,10种常见体系架构模式之一)
一.简介: 架构模式是一个通用的.可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题.架构模式与软件设计模式类似,但具有更广泛的范围. 模型-视图-控制器模式,也称为MVC模式.是软件 ...
- 设计模式-结构型模式, mvc 模型视图控制器模式(8)
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式.这种模式用于应用程序的分层开发. Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO.它 ...
- [框架模式]经典的模型视图控制器模式MVC
参考:<设计模式> http://blog.csdn.net/u010168160/article/details/43150049 百度百科 引言: Model(模型)是应用程序中用于处 ...
- MVC详解(转)
原文链接:MVC详解 MVC与模板概念的理解 MVC(Model View Controller)模型-视图-控制器 MVC本来是存在于Deskt op程序中的,M是指数据模型,V是指用户界面,C ...
- 设计模式 --- 模型-视图-控制器(Model View Controller)
模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程 ...
- MODEL-View-Controller,既模型-视图-控制器
Swing组件采用MVC(MODEL-View-Controller,既模型-视图-控制器)设计模式,其中模型(Model)用于维护组件的各种状态,视图(View)是组件的可视化表现,控制器(Cont ...
随机推荐
- Linux NFS 说明,配置及故障分析
一.NFS服务简介 NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操 ...
- CLOSE_WAIT状态的原因与解决方法 --转
转自:http://blog.chinaunix.net/uid-20357359-id-1963662.html 这个问题之前没有怎么留意过,是最近在面试过程中遇到的一个问题,面了两家公司,两家公司 ...
- Android 自学之线性布局 LinearLayout
线性布局(LinearLayout),线性布局有点想AWT编程里面的FolwLayout,他们都会将容器里面的组件挨个的排列起来. 他们最大的区别在于:Android的线性布局不会换行:AWT里面的F ...
- haproxy部署及配置
HAProxy介绍 (1)HAProxy 是一款提供高可用性.负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProxy特 ...
- Clean Code 笔记 (一):命名
一.命名规范1.名副其实,通过名称我们知道它为什么存在,它做什么事,该怎么用2.避免误导,避免使用与本意相悖的词,提防使用不同之处较小的名称3.有意义的区分,去掉多余的废话比如:a,the.缺少明确约 ...
- 简论数据库乐观悲观锁与并发编程中的CAS
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/5783205. ...
- modelsim打开.wlf文件的方法(原创)
运行vsim -c -l vsim.log -wlf vsim.wlf work.tb work.glbl之后,会在不启动modelsim的情况下完成仿真,并且会把仿真波形记录下来(以.wlf文件格式 ...
- .Net Framework 各个版本新特性总结 (一)
.Net Framework 4.5 新特性 最近面试时又看到有问.Net Framework 新特性的问题,一时被问到了.平时也是拿起来就用,新版本出来了,新特性也就是瞄一眼,也没去仔细查看.这次干 ...
- 【转】浅谈Java中的hashcode方法(这个demo可以多看看)
浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...
- Linq 的IQueryable和IEnumerable方式
IEnumerable方式: public IEnumerable<WebManageUsers> GetWebManageUsers(ISpecification<WebManag ...