很早就知道有这三个概念,但是一直都不清楚是怎么回事,在网上搜索,都是泛泛而谈,没有具体例子,新手是看不懂的,直到找到这篇文章,我对这三个架构有了更清楚的了解。

从一个简单的例子去研究这三个架构。

注意,MVC,MVP,MVVM中的C,P,VM,下文都要controller指代。

需求如下

界面上显示100,以及两个按钮,其中一个点一下加1,另外一个点一下减1

如图

诚然,这么简单的需求,并不需要用什么架构去完成,可是如果是复杂的需求,要长篇大论才能说完,所以只拿简单的来做例子,实际开发中,你在完成一个需求之前,是需要好好掂量是否要用架构,要的话,用什么架构(不局限于这三个),架构里面又要用什么设计模式等等。经过我的实践,发现,即使是架构改变了,view是可以完全不变的,所以先展现view层的代码。

html部分

<span id="text">100</span>
<button id="upBtn">up</button>
<button id="downBtn">down</button>

js部分

function $(id) {
return document.querySelector(`#${id}`);
}
function View(controller) {
const upBtn = $('upBtn');
const downBtn = $('downBtn');
const textSpan = $('text'); this.render = function(model) {
textSpan.innerHTML = model.getValue();
}
upBtn.onclick = controller.up;
downBtn.onclick = controller.down;
}

render方法是核心,方法名称不能改(后面要依赖这个render方法),其中要实现数据的展示逻辑,然后是一些点击事件的绑定

MVC

model层

function Model() {
let value = 100;
this.up = function() {
value += 1;
};
this.down = function() {
value -= 1;
};
this.getValue = function() {
return value;
};
}

保存数据,并提供访问,修改数据的方法,如果仅仅是这样,那么当model改变时,view是不知道的,所以需要让model去通知view,我数据改变了,你要更新了。怎么做呢?利用观察者模式。在model中,增加一个数组views,去保存这个model对应的视图,在修改数据的时候,遍历views数组,调用每个view的render方法,参数是自己。

修改后的model

function Model() {
let value = 100;
const self = this;
const views = [];
this.up = function() {
value += 1;
};
this.down = function() {
value -= 1;
};
this.getValue = function() {
return value;
};
this.broadcast = function() {
views.forEach(view => view.render(self));
};
this.subscribe = function(cb) {
views.push(cb);
}
}

仔细看修改后的model,虽然增加了通知的方法(broadcast),但是在修改数据的方法(up和down)中并没有去通知视图。这个工作是由controller承担的,另外把view注册到model中,也是controller做的。

controller层

function Controller() {
let view = null;
let model = null;
this.up = function() {
// 修改数据
model.up();
// 通知视图
model.broadcast();
};
this.down = function() {
model.down();
model.broadcast();
}
this.init = function() {
view = new View(this);
model = new Model();
// 把视图注册到model中
model.subscribe(view);
}
}

可以看到,controller把自己传给了view去创建视图,同时保存引用,创建model后,把view注册到model中。同时实现了,改变数据,通知视图的工作。

请一定要好好理解MVC,后面的MVP,MVVM都只是稍加修改而已。

MVP

在MVC中,改变数据,通知视图,都是在controller做的,注册视图,以及通知视图,这两个方法的实现,都是model完成的,既然model负责数据处理,这两个工作实际上和改变数据是没关系的,把他们都转移到controller中,不仅可以让model层专注于数据处理,同时也方便多个视图共用一个controller

model层

function Model() {
let value = 100;
this.up = function() {
value += 1;
};
this.down = function() {
value -= 1;
};
this.getValue = function() {
return value;
};
}

model层更小了,删除了注册,通知方法,只保存数据和提供获取,修改数据的方法

controller层

function Controller() {
let views = [];
let model = null;
function broadcast() {
views.forEach(view => view.render(model));
}
this.up = function() {
model.up();
broadcast();
};
this.down = function() {
model.down();
broadcast();
}
this.init = function() {
views.push(new View(this));
model = new Model();
}
}

controller,增加了广播方法,该方法的实现和调用都在controller中,另外,如果想多个视图共用一个controller,如果这多个视图都是同一个model,上面代码能够胜任,如果是这多个视图是不同的model,那就要自己去实现好view和model的对应关系了(要用map来存储对应关系,一个数组做不到)。

MVVM

可以看到,在MVP中,model也有一个up方法,controller也有一个up方法,只是增加了一个广播方法的调用。是不是有些重复呢?把这两个类似的方法整合到controller,model只负责保存数据,不实现修改数据的逻辑,这就是MVVM了,极大地精简model

model层

function Model() {
let value = 100;
this.getValue = function() {
return value;
};
this.setValue = function(v) {
value = v;
}
}

其实,不用函数,单纯地用一个变量,也是可以的,但是为了view层不变,view层中依赖model的getValue方法,所以这里还是用函数去实现model

controller层

function Controller() {
let views = [];
let model = null;
function broadcast() {
views.forEach(view => view.render(model));
}
this.up = function() {
model.setValue(model.getValue() + 1);
broadcast();
};
this.down = function() {
model.setValue(model.getValue() - 1);
broadcast();
}
this.init = function() {
views.push(new View(this));
model = new Model();
}
}

精简model的代价是controller要做更多的事情,实现修改数据的逻辑,通知视图。如果用框架,react或者vue,通知视图这部分框架会帮你实现,只要实现数据修改的逻辑就好了。

至此,三个架构都讲完了,如果错误,欢迎讨论。

代码可在github上下载,需要node环境。

参考资料:http://www.cnblogs.com/zhouyangla/p/6936455.html

实例说明MVC,MVP,MVVM架构的更多相关文章

  1. 前端mvc mvp mvvm 架构介绍(vue重构项目一)

    首先 我们为什么重构这个项目 1:我们现有的技术是前后台不分离,页面上采用esayUI+jq构成的单页面,每个所谓的单页面都是从后台胜场的唯一Id 与前端绑定,即使你找到了那个页面元素,也找不到所在的 ...

  2. 热门前沿知识相关面试问题-MVC/MVP/MVVM架构设计模式面试问题详解

    MVC[最常用]: MVC的定义:M:业务逻辑处理.[业务MODEL]V:处理数据显示的部分.[如xml布局文件]C:Activity处理用户交互的问题.[也就是Activity在MVC中扮演着C的角 ...

  3. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...

  4. [转]MVVM架构~mvc,mvp,mvvm大话开篇

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一 ...

  5. Android App的设计架构:MVC,MVP,MVVM与架构AAAAA

    1. 架构设计的目的1.1 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.1.2 这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续 ...

  6. 浅析前端开发中的 MVC/MVP/MVVM 模式

    MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式.不同于设计模式(Design Pattern),只是为了解决一类 ...

  7. MVC, MVP, MVVM比较以及区别(上)

    MVC, MVP和MVVM都是用来解决界面呈现和逻辑代码分离而出现的模式.以前只是对它们有部分的了解,没有深入的研究过,对于一些里面的概念和区别也是一知半解.现在一边查资料,并结合自己的理解,来谈一下 ...

  8. android MVC && MVP && MVVM分析和对比

    相关:http://www.cnblogs.com/wytiger/p/5305087.html 出处http://blog.csdn.net/self_study,对技术感兴趣的同鞋加群544645 ...

  9. MVC, MVP, MVVM比较以及区别

    MVC, MVP和MVVM都是用来解决界面呈现和逻辑代码分离而出现的模式.以前只是对它们有部分的了解,没有深入的研究过,对于一些里面的概念和区别也是一知半解.现在一边查资料,并结合自己的理解,来谈一下 ...

随机推荐

  1. ascii codec can't decode byte 0xe8 in position 0:ordinal not in range(128) python代码报错

    import sys reload(sys) sys.setdefaultencoding('utf-8')

  2. python编码错误的解决办法 SyntaxError: Non-ASCII character '\xe5' in file

    [提出问题]. 在编写Python时,当使用中文输出或注释时运行脚本,会提示错误信息: SyntaxError: Non-ASCII character '\xe5' in file ******* ...

  3. CSS display使用

    .今天我们来分析一下display的一些用法,display样式在我们整个CSS设置中,非常重要,掌握好display,才能有效的解决CSS布局的问题,在理解display之前,我们先了解两个概念:块 ...

  4. ASP.NET 控制器

    1.继承Controller public class TestController : Controller2.编写控制器方法    // URL  :   test/Edit/1        [ ...

  5. 转: 【Java并发编程】之二十一:并发新特性—阻塞队列和阻塞栈(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17511147 阻塞队列 阻塞队列是Java5并发新特性中的内容,阻塞队列的接口是Java. ...

  6. Git和Github使用

    什么是Git? Git 是一个快速.可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问. 版本控制 简单地说,就是将在本地开发的代码,定时推送到服务器.每一次修改, ...

  7. 201521123074 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  8. 201521123093 java 第五周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 答:接口:1.所有的默认方法都是public abstract; 2.属性都是p ...

  9. 201521123122 《java程序设计》 第四周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 这个思维导图比较简单,详细内容点击此处 2. 书面作业 注释的应用 使用类的注释与方法的注释 ...

  10. JAVA课设---五子棋

    1.团队博客链接 JAVA课设-五子棋-团队博客 2.个人负责模块: ①对鼠标事件的处理 , 此模块需处理五子棋的放置问题.颜色转换问题.以及当五子连线时弹出窗口显示结果. ②对MainFrame中主 ...