定义
MVC 全称是 Model-View-Controller(模型 - 视图 - 控制器) ,是一种软件设计典范,用一种业务逻辑、数据、界面进行分离的开发模式。
MVC 模式是一种经典的设计模式,被广泛地应用在程序开发当中,例如,目前比较知名的经典框架:Spring MVC、ASP.NET MVC、Struts2 等,都是基于 MVC 模式实现的。
组成角色
MVC 模式包含如下角色:
- Model(模型):用于存储和操作数据(库)的类,可以是存储容器,也可以带有逻辑,用于返回结果给控制器;
- View(视图):展示给用户的界面,用于展示和操作;
- Controller(控制器):用于连接模型层和视图层的中间控制器。
角色之间的执行流程图如下:
MVC 模式代码实现
本文并不打算使用现成的 MVC 框架来做演示,比如 Spring MVC 框架等,因为本身框架太重,且已经是封装好的,不便于读者理解,所以本文会用代码的方式,手动实现 MVC 模式。
模型层
/**
* 模型层(伪代码)
*/
class Model {
public static void method() {
System.out.println("I'm Model.");
}
}
视图层
/**
* 视图层(伪代码)
**/
class View {
public void show() {
System.out.println("I'm View.");
Controller.doController();
}
}
客户端调用
/**
* 客户端调用(伪代码)
*/
public class Client {
public static void main(String[] args) {
// 打开页面
View view = new View();
// 执行查询,并展现结果
view.show();
}
}
程序执行结果如下:
I’m View.
I’m Controller.
I’m Model.
以上模型层、视图层、客户端调用都是伪代码,模拟的是用户打开页面,再执行查询、展示的流程,程序的实际执行流程是:用户先调用视图层(页面),视图层再调用控制器,控制器再调用模型层,最终再把结果返回给用户的过程。
优缺点
MVC 模式的优点:
- 分工明确:有利于团队开发分工协作和质量控制,降低开发成本;
- 耦合性低:模块间相互比较独立,比如,在业务流程和交互方式不变的情况下,可以任意调整前端页面的样式,而不影响其他模块;
- 重用性高:以模型层来说,可以提供给多个控制器来使用。
MVC 模式的缺点: - 增加了系统实现的复杂性,对于简单的应用并不适用;
- 减低了系统的运行性能,因为程序的执行经过的层数过多,所以会带来一定的性能损耗。
应用场景
MVC 模式典型应用场景如下: - Web 开发领域:由于 Web 开发的特殊性,采用 MVC 进行结构划分,一方面会提升团队的协同开发效率,专人干专事,另一方面也有利于日后软件产品的维护和升级,同时能够提升软件模块的复用性;
- 移动互联开发:目前移动互联开发,比如:Android、iOS 开发也在采用 MVC 框架,对于这种展示层修改频率比较高的应用,采用 MVC 的方式,使得修改展示层更加的高效;
- 实用型工具类程序:与前两种开发不同,实用型工具类程序,更多修改的是展示层之外的代码,这种在不更改用户操作习惯的方式下,静默地调整和升级代码的方式,也比较适合用 MVC 设计模式。
使用实例
以图书馆中查询书籍简介为例,比如,我们在图书馆的电脑上,输入书名再点击查询,就会在数据库中查询书籍信息,并展示给用户,具体实现代码如下。
模型层
/**
* 模型层
**/
class MvcModel {
private String name;
private String desc;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
前端页面(视图层)
/**
* 视图层
**/
class MvcView {
public String name;
public MvcView() {
System.out.println("页面展示");
}
// 接收用户请求,调用控制器
public void find() {
// 调用控制器,输出结果
System.out.println("输出结果:" + new MvcController().getDesc(name));
}
}
控制器
/**
* 控制器(层)
**/
class MvcController {
/**
* @return 简介内容
* @Description 根据名称获取简介
* @Param name 名称
**/
public String getDesc(String name) {
// 最终返回的结果
String result = "暂无";
// 以模型层为基础,通过数据层,查询到相关的数据
MvcModel mvcModel = MvcDB.findByName(name);
if (mvcModel != null) {
result = mvcModel.getDesc();
}
return result;
}
}
数据层(提供数据)
**
* 数据层
**/
class MvcDB {
/**
* @Description 根据书名返回数据
* @Param name 书名
* @return 模型对象数据
**/
public static MvcModel findByName(String name) {
MvcModel model = null;
switch (name) {
case "Java":
model = new MvcModel();
model.setName("Java面试全解析");
model.setDesc("这是一本包含了 505 道面试题的 Java 书籍。");
break;
case "MySQL":
model = new MvcModel();
model.setName("MySQL面试金典");
model.setDesc("这是一本包含了 208 道面试题的 MySQL 书籍。");
break;
default:
break;
}
return model;
}
}
客户端调用
public class Client {
public static void main(String[] args) {
// 打开页面
MvcView mvcView = new MvcView();
// 输入书名:Java
mvcView.name = "Java";
// 点击查询,执行相关流程并展示结果
mvcView.find();
// 输入书名:MySQL
mvcView.name = "MySQL";
// 点击查询,执行相关流程并展示结果
mvcView.find();
}
}
程序执行结果如下:
页面展示
输出结果:这是一本包含了 505 道面试题的 Java 书籍。
输出结果:这是一本包含了 208 道面试题的 MySQL 书籍。
细心的读者可能会发现,这个实例中又多了一个数据层,其实它并没有特殊的含义,只是为整个实例提供数据来源而已。在这个实例中,模型层相对来说功能比较单一,只是一个数据载体(数据容器)而已,但广义上来说 MVC 模式中的模型层,也可以是业务模型层,并带有逻辑判断代码,就相当于这个例子中的 MvcModel 类 + MvcDB 类的合体。但设计模式只是一种思想,并没有严格的实现标准,这同时也是学习设计模式的精髓,读者可以根据实际情况,灵活变通,只要符合程序设计的七大经典原则即可。
总结
MVC 模式 Model-View-Controller(模型 - 视图 - 控制器),可以有效地将程序分层,提高了开发效率,让专业的人干专业的事,同时降低了代码间的耦合,提升了代码的复用性,但也因此减低了程序的执行性能,拉长了程序调试的流程,增加了开发的难度。所以对于中小型系统来说,要谨慎地使用 MVC 模式,不要死记硬套,要学会变通地使用各种设计模式。