JS常用设计模式(MVC、MVP、MVVM及其他设计模式)

JavaScript029

JS常用设计模式(MVC、MVP、MVVM及其他设计模式),第1张

一、MVC

MVC模式的意思是,软件可以分成三个部分。

视图(View):用户界面。

控制器(Controller):业务逻辑

模型(Model):数据保存

各部分之间的通信方式如下。

View 传送指令到 Controller

Controller 完成业务逻辑后,要求 Model 改变状态

Model 将新的数据发送到 View,用户得到反馈

所有通信都是单向的。

二、互动模式

接受用户指令时,MVC 可以分成两种方式。一种是通过 View 接受指令,传递给 Controller。

另一种是直接通过controller接受指令。

三、实例:Backbone

实际项目往往采用更灵活的方式,以 Backbone.js 为例。

1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。

2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。

3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。所以,Backbone 索性取消了 Controller,只保留一个 Router(路由器) 。

四、MVP

MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。

1. 各部分之间的通信,都是双向的。

2. View 与 Model 不发生联系,都通过 Presenter 传递。

3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

五、MVVM

MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。

唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。 Angular 和 Ember 都采用这种模式。

1、js工厂模式

说明:

在函数中定义对象,并定义对象的各种属性,虽然属性可以为方法,但是建议将属性为方法的属性定义到函数之外,这样可以避免重复创建该方法。

引用该对象的时候,这里使用的是 var x = Parent()而不是 var x = new object()因为后者可能会出现很多问题(前者也成为工厂经典方式,后者称之为混合工厂方式),不推荐使用new的方式使用该对象。

在函数的最后返回该对象。

不推荐使用这种方式创建对象,但应该了解。  

2、js构造函数模式

说明:

与工厂方式相比,使用构造函数方式创建对象无需在函数内部创建对象,而使用this指代,并而函数无需明确return。

同工厂模式一样,虽然属性的值可以为方法,仍建议将该方法定义在函数之外。

同样的,不推荐使用这种方式创建对象,但仍需了解。

3、js原型模式

说明:

函数中不对属性进行定义。

利用prototype属性对属性进行定义。

同样的额,不推荐使用这样的方式创建对象。

4、构造函数+原型的js混合模式(推荐)

说明:

该模式是指混合搭配使用构造函数和原型方式。

将所有的属性,不是方法的定义在函数中(构造函数的方式),将所有属性值为方法的利用prototype在函数之外定义(原型方式)。

推荐使用这样的方式创建对象,这样有好处。

5、构造函数+原型的动态原型模式(推荐)

说明:

动态原型方式可以理解为混合构造函数,原型方式的一个特例。

该模式中,属性为方法的属性直接在函数中进行了定义,但是因为

if(typeof Parent.lev == "undefined"){

          Parent.prototype.lev = function(){

            return this.name

          }

   Parent.lev = true

    } 

从而保证创建该对象的实例时,属性的方法不会被重复的创建。

先给你介绍下JS常用的几种模式

1.原始模式

    //1.原始模式,对象字面量方式

var person = { 

    name: 'Jack',

    age: 18,

    sayName: function () { alert(this.name) }

}

//1.原始模式,Object构造函数方式

var person = new Object()

person.name = 'Jack'

person.age = 18

person.sayName = function () {

    alert(this.name)

}

/*显然,当我们要创建批量的person1、person2……时,

每次都要敲很多代码,资深copypaster都吃不消!

然后就有了批量生产的工厂模式。*/

2.工厂模式

//2.工厂模式,定义一个函数创建对象

function creatPerson (name, age) {

    var person = new Object() 

    person.name = name

    person.age = age

    person.sayName = function () {

        alert(this.name)

    }

    return person 

}

/*

 工厂模式就是批量化生产,简单调用就可以进入造人模式(啪啪啪……)。

 指定姓名年龄就可以造一堆小宝宝啦,解放双手。

 但是由于是工厂暗箱操作的,所以你不能识别这个对象到底是什么类型、

 是人还是狗傻傻分不清(instanceof 测试为 Object),

 另外每次造人时都要创建一个独立的temp对象,代码臃肿,雅蠛蝶啊。

*/

3.构造函数

//3.构造函数模式,为对象定义一个构造函数

function Person (name, age) {

    this.name = name

    this.age = age

    this.sayName = function () {

        alert(this.name)

    }    

}

var p1 = new Person('Jack', 18) //创建一个p1对象

Person('Jack', 18)   

 //属性方法都给window对象,window.name='Jack',window.sayName()会输出Jack

 

 

 4.原型模式

 //4.原型模式,直接定义prototype属性

function Person () {}

Person.prototype.name = 'Jack'

Person.prototype.age = 18

Person.prototype.sayName = function () { alert(this.name) }

//4.原型模式,字面量定义方式

function Person () {}

Person.prototype = {

    name: 'Jack',

    age: 18,

    sayName: function () { alert(this.name) }

}

var p1 = new Person() //name='Jack'

var p2 = new Person() //name='Jack'

//这里需要注意的是原型属性和方法的共享,即所有实例中

//都只是引用原型中的属性方法,任何一个地方产生的改动会引起其他实例的变化。

5.混合模式(构造+原型)

//5. 原型构造组合模式,

function Person (name, age) {

    this.name = name

    this.age = age

}

Person.prototype = {

    hobby: ['running','football']

    sayName: function () { alert(this.name) },

    sayAge: function () { alert(this.age) }

}

var p1 = new Person('Jack', 20) 

//p1:'Jack',20 __proto__: ['running','football'],sayName,sayAge

var p2 = new Person('Mark', 18) 

//p1:'Mark',18__proto__: ['running','football'],sayName,sayAge

//通过上面的例子,有什么区别一目了然

如果有许多地方都需要生成A的对象,那么你需要写很多A a=new A()。

如果需要修改的话,你要修改许多地方。

但是如果用工厂模式,你只需要修改工厂代码。其他地方引用工厂,可以做到只修改一个地方,其他代码都不动,就是解耦了。