浅析Android开发中的-MVC-MVP-MVVM-模式

var val = 0;

this.add = function(v) {
if (val < 100) val += v;
};

this.sub = function(v) {
if (val > 0) val -= v;
};

this.getVal = function() {
return val;
};

/* 观察者模式 */
var self = this,
views = [];

this.register = function(view) {
views.push(view);
};

this.notify = function() {
for(var i = 0; i < views.length; i++) {
views[i].render(self);
}
};
};复制代码

Model和View之间使用了观察者模式,View事先在此Model上注册,进而观察Model,以便更新在Model上发生改变的数据。

View

view和controller之间使用了策略模式,这里View引入了Controller的实例来实现特定的响应策略,比如这个栗子中按钮的 click 事件:

myapp.View = function(controller) {
var $num = $(‘#num’),
$incBtn = $(‘#increase’),
$decBtn = $(‘#decrease’);

this.render = function(model) {
$num.text(model.getVal() + ‘rmb’);
};

/* 绑定事件 */
$incBtn.click(controller.increase);
$decBtn.click(controller.decrease);
};复制代码

如果要实现不同的响应的策略只要用不同的Controller实例替换即可。

Controller

控制器是模型和视图之间的纽带,MVC将响应机制封装在controller对象中,当用户和你的应用产生交互时,控制器中的事件触发器就开始工作了。

myapp.Controller = function() {
var model = null,
view = null;

this.init = function() {
/* 初始化Model和View */
model = new myapp.Model();
view = new myapp.View(this);

/* View向Model注册,当Model更新就会去通知View啦 */
model.register(view);
model.notify();
};

/* 让Model更新数值并通知View更新视图 */
this.increase = function() {
model.add(1);
model.notify();
};

this.decrease = function() {
model.sub(1);
model.notify();
};
};复制代码

这里我们实例化View并向对应的Model实例注册,当Model发生变化时就去通知View做更新,这里用到了观察者模式。

当我们执行应用的时候,使用Controller做初始化:

(function() {
var controller = new myapp.Controller();
controller.init();
})();复制代码

可以明显感觉到,MVC模式的业务逻辑主要集中在Controller,而前端的View其实已经具备了独立处理用户事件的能力,当每个事件都流经Controller时,这层会变得十分臃肿。而且MVC中View和Controller一般是一一对应的,捆绑起来表示一个组件,视图与控制器间的过于紧密的连接让Controller的复用性成了问题,如果想多个View共用一个Controller该怎么办呢?这里有一个解决方案:

来把王者荣耀压压惊~其实我想说的是MVP模式…

MVP

MVP(Model-View-Presenter)是MVC模式的改良,由IBM的子公司Taligent提出。和MVC的相同之处在于:Controller/Presenter负责业务逻辑,Model管理数据,View负责显示。

虽然在MVC里,View是可以直接访问Model的,但MVP中的View并不能直接使用Model,而是通过为Presenter提供接口,让Presenter去更新Model,再通过观察者模式更新View。

与MVC相比,MVP模式通过解耦View和Model,完全分离视图和模型使职责划分更加清晰;由于View不依赖Model,可以将View抽离出来做成组件,它只需要提供一系列接口提供给上层操作。

Model

myapp.Model = function() {
var val = 0;

this.add = function(v) {
if (val < 100) val += v;
};

this.sub = function(v) {
if (val > 0) val -= v;
};

this.getVal = function() {
return val;
};
};复制代码

Model层依然是主要与业务相关的数据和对应处理数据的方法。

View

myapp.View = function() {
var $num = $(‘#num’),
$incBtn = $(‘#increase’),
$decBtn = $(‘#decrease’);

this.render = function(model) {
$num.text(model.getVal() + ‘rmb’);
};

this.init = function() {
var presenter = new myapp.Presenter(this);

$incBtn.click(presenter.increase);
$decBtn.click(presenter.decrease);
};
};复制代码

MVP定义了Presenter和View之间的接口,用户对View的操作都转移到了Presenter。比如这里可以让View暴露setter接口以便Presenter调用,待Presenter通知Model更新后,Presenter调用View提供的接口更新视图。

Presenter

myapp.Presenter = function(view) {
var _model = new myapp.Model();
var _view = view;

_view.render(_model);

this.increase = function() {
_model.add(1);
_view.render(_model);
};

this.decrease = function() {
_model.sub(1);
_view.render(_model);
};
};复制代码

Presenter作为View和Model之间的“中间人”,除了基本的业务逻辑外,还有大量代码需要对从View到Model和从Model到View的数据进行“手动同步”,这样Presenter显得很,维护起来会比较困难。而且由于没有数据绑定,如果Presenter对视图渲染的需求增多,它不得不过多关注特定的视图,一旦视图需求发生改变,Presenter也需要改动。

运行程序时,以View为入口:

(function() {
var view = new myapp.View();
view.init();
})();复制代码

MVVM

MVVM(Model-View-ViewModel)最早由微软提出。ViewModel指 “Model of View”——视图的模型。这个概念曾在一段时间内被前端圈热炒,以至于很多初学者拿jQuery和Vue做对比…

MVVM把View和Model的同步逻辑自动化了。以前Presenter负责的View和Model同步不再手动地进行操作,而是交给框架所提供的数据绑定功能进行负责,只需要告诉它View显示的数据对应的是Model哪一部分即可。

这里我们使用Vue来完成这个栗子。

Model

在MVVM中,我们可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为(格式化数据由View的负责),这里可以把它理解为一个类似json的数据对象。

var data = {
val: 0
};复制代码

View

和MVC/MVP不同的是,MVVM中的View通过使用模板语法来声明式的将数据渲染进DOM,当ViewModel对Model进行更新的时候,会通过数据绑定更新到View。写法如下:

{{ val }}rmb
- +
复制代码

ViewModel

ViewModel大致上就是MVC的Controller和MVP的Presenter了,也是整个模式的重点,业务逻辑也主要集中在这里,其中的一大核心就是数据绑定,后面将会讲到。与MVP不同的是,没有了View为Presente提供的接口,之前由Presenter负责的View和Model之间的数据同步交给了ViewModel中的数据绑定进行处理,当Model发生变化,ViewModel就会自动更新;ViewModel变化,Model也会更新。

new Vue({
el: ‘#myapp’,
data: data,
methods: {
add(v) {
if(this.val < 100) {
this.val += v;
}
},
sub(v) {
if(this.val > 0) {
this.val -= v;
}
}
}
});复制代码

整体来看,比MVC/MVP精简了很多,不仅仅简化了业务与界面的依赖,还解决了数据频繁更新(以前用jQuery操作DOM很繁琐)的问题。因为在MVVM中,View不知道Model的存在,ViewModel和Model也察觉不到View,这种低耦合模式可以使开发过程更加容易,提高应用的可重用性。

数据绑定

双向数据绑定,可以简单而不恰当地理解为一个模版引擎,但是会根据数据变更实时渲染。——《界面之下:还原真实的MV*模式》

在Vue中,使用了双向绑定技术(Two-Way-Data-Binding),就是View的变化能实时让Model发生变化,而Model的变化也能实时更新到View。

“据说这玩意儿可以申请专利呢”

不同的MVVM框架中,实现双向数据绑定的技术有所不同。目前一些主流的前端框架实现数据绑定的方式大致有以下几种:

  • 数据劫持 (Vue)
  • 发布-订阅模式 (Knockout、Backbone)
  • 脏值检查 (Angular)

我们这里主要讲讲Vue。

Vue采用数据劫持&发布-订阅模式的方式,通过ES5提供的 Object.defineProperty() 方法来劫持(监控)各属性的 getter 、setter ,并在数据(对象)发生变动时通知订阅者,触发相应的监听回调。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。要实现Vue中的双向数据绑定,大致可以划分三个模块:Observer、Compile、Watcher,如图:

  • Observer 数据监听器
    负责对数据对象的所有属性进行监听(数据劫持),监听到数据发生变化后通知订阅者。

  • Compiler 指令解析器
    扫描模板,并对指令进行解析,然后绑定指定事件。

  • Watcher 订阅者
    关联Observer和Compile,能够订阅并收到属性变动的通知,执行指令绑定的相应操作,更新视图。Update()是它自身的一个方法,用于执行Compile中绑定的回调,更新视图。

数据劫持

一般对数据的劫持都是通过Object.defineProperty方法进行的,Vue中对应的函数为 defineReactive ,其普通对象的劫持的精简版代码如下:

var foo = {
name: ‘vue’,
version: ‘2.0’
}

function observe(data) {

总结

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

Android大厂面试真题全套解析

2017-2020字节跳动Android面试真题解析PDF
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

[外链图片转存中…(img-GXQA62rG-1715334838587)]

[外链图片转存中…(img-t9Ne7T9z-1715334838588)]
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值