avatar

目录
框架设计概念

MVC

MVC即Model View Controller即模型 视图 控制器

  • View:是这个js模块对应在HTML中的部分,就是展示给用户看的部分
  • Model:可以从服务器获取数据,把数据给Controller。还要将Controller监听到的用户提交的数据上传到服务器
  • Controller:调用model的数据,用来更新View。还要监听用户在View上的操作,获取用户提交的数据,传给model

Controller其实就是联系Model和View的桥梁,Controller拿到Model,然后将Model放到View里

http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

MVVM

设计模式

前言

为什么要封装代码

写代码要又良好的封装,要搞内聚,低耦合。

  • 封装好的代码,内部变量不会污染外部
  • 可以作为一个模块给外部调用,外部调用者不需要如何实现,只需要会用即可
  • 对外扩展开放,对修改关闭,即开闭原则。外部不能修改模块

工厂模式

工厂模式的名字就很直白,封装的模块就像一个工厂一样批量产出需要的对象,常见的工厂模式的一个特征就是调用的时候不需要用new,而且传入的参数比较简单。但是调用次数可能比较频繁,经常需要产出不同的对象,频繁调用时不用new也方便很多。一个工厂模式的代码结构:

Javascript
1
2
3
4
5
6
7
8
9
10
function factory(type) {
switch(type) {
case "type1":
return new Type1();
case "type2":
return new Type2();
case "type3":
return new Type3();
}
}

上述代码中,传入了type,然后工厂根据不同的type来创建不同的对象

实例:弹窗组件

需求:消息型弹窗,确认型弹窗,确认型弹窗,他们的颜色和内容都是不一样的

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function info(content,color){}
function confirm(content,color){}
function cancel(content,color){}

function popup(type,content,color){
switch(type){
case "info":
return new info(content,color);
case "confirm":
return new confirm(content,color);
case "cancel":
return new cancel(content,color);
}
}

调用之后就可以不用使用new

Javascript
1
let info = popop("info",content,color);

改造成面向对象

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function popup(type, content, color) {
// 如果是通过new调用的,返回对应类型的弹窗
if(this instanceof popup) {
return new this[type](content, color);
} else {
// 如果不是new调用的,使用new调用,会走到上面那行代码
return new popup(type, content, color);
}
}

// 各种类型的弹窗全部挂载在原型上成为实例方法
popup.prototype.infoPopup = function(content, color) {}
popup.prototype.confirmPopup = function(content, color) {}
popup.prototype.cancelPopup = function(content, color) {}

封装成模块

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function(){
function popup(type, content, color) {
if(this instanceof popup) {
return new this[type](content, color);
} else {
return new popup(type, content, color);
}
}

popup.prototype.infoPopup = function(content, color) {}
popup.prototype.confirmPopup = function(content, color) {}
popup.prototype.cancelPopup = function(content, color) {}

window.popup = popup;
})()

// 外面就直接可以使用popup模块了
let infoPopup1 = popup('infoPopup', content, color);

建造者模式

创建者模式是用于比较复炸的大对象构建,比如VueVue内部包含一个功能强大,逻辑复杂的对象,在构建的时候也需要传很多参数进去,像这种需要创建的情况不多,创建的对象本身又复杂的时候就使用建造者模式。建造者模式的一般结构如下:

Javascript
1
2
3
4
5
6
7
8
function Model(){}
function Mode2(){}

function Final(){
this.model1 = new Model1();
this.model2 = new Model2();
}
const obj = new Final();

实例:

需求:写一个编辑器插件,初始化的时候需要配置大量参数,而且内部的功能很多很复杂,可以改变字体颜色和大小,也可以前进后退。

一般一个页面就只有一个编辑器,而且里面的功能可能很复杂,可能需要调整颜色,字体等。也就是说这个插件内部可能还会调用其他类,然后将他们组合起来实现功能,这就适合建造者模式。我们来分析下做这样一个编辑器需要哪些模块:

  1. 编辑器本身肯定需要一个类,是给外部调用的接口
  2. 需要一个控制参数初始化和页面渲染的类
  3. 需要一个控制字体的类
  4. 需要一个状态管理的类
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Editor{
constructor(){
// 编辑器里面就算将各个模块组合起来实现功能
this.initer = new HtmlInit();
this.fontController = new FontController();
this.stateController = new StateController(this.fontController);
}
}

// 初始化参数
class HtmlInit {
initStyle(){} // 初始化样式
renderDom(){} // 渲染DOM
}

// 字体控制器
class FontController {
changeFontColor(){} // 改变字体颜色
changeFontSize(){} // 改变字体大小
}

class StateController {
constructor(fontController){
this.states = []; // 存储所有状态
this.currentState = 0; // 指向当前状态
this.fontController = fontController; // 将字体管理器注入
}
saveState(){} // 保存状态
backState(){} // 后退状态
forwardState(){} // 前进状态
}

单例模式

定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点

Javascript
1
2
3
4
5
6
7
8
9
function Singleton(){}

Singleton.getInstance = function(){
if(this.instance){
return this.instance;
}
this.instance = new Singleton();
return this.instance;
}

SingletongetInstance,这个方法会检测是不是又现存的实例对象,如果又就返回,没有就新建一个

实例:

需求:一个全局的数据对象进行管理,这个对象只能有一个,如果有多个会导致数据不同步

这个需求要求全局只有一个数据存储对象,是典型的适合单例模式的场景,我们可以直接套用上面的代码模板,但是上面的代码模板获取instance必须要调用getInstance才行,要是某个使用者直接调用Singleton()或者new Singleton()就会出问题,这次我们换一种写法,让他们能够兼容Singleton()new Singleton(),使用起来更加傻瓜化

Javascript
1
2
3
4
5
6
7
function store(){
if(store.instance) {
return store.instance;
}

store.instance = this;
}

上述代码支持使用new store()的方式调用,我们使用了一个静态变量instance来记录是否有进行过实例化,如果实例化了就返回这个实例,如果没有实例化说明是第一次调用,那就把this赋给这个这个静态变量,因为是使用new调用,这时候的this指向的就是实例化出来的对象,并且最后会隐式的返回this

如果我们还想支持store()直接调用,我们可以用前面工厂模式用过的方法,检测this是不是当前类的实例,如果不是就帮他用new调用就行了:

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function store(){
if(!(this instanceof store)){
return new store();
}

if(store.instance) {
return store.instance;
}
store.instance = this;
}

let a = new store();
let b = store();
a === b // true

原型模式

原型模式最经典的应用就算JS本身,JS的原型链就算原型模式。JS中可以使用Objcet.create指定一个对象作为原型来创建对象:

Javascript
1
2
3
4
5
6
7
8
const obj = {
x: 1,
func: ()=>{}
}

const newObj = Object.create(obj);
console.log(newObj.__proto__ === obj); // true
console.log(newObj.x) //1

装饰者模式

指在不修改原有代码的情况下增加新功能

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function sleep(who) {
who?console.log(who + '睡觉'):console.log('睡觉')

}
Function.prototype.before = function (callback) {
return (...args)=> {// args 传入的参数数组
callback()
args?this(...args):this() // 传入参数
}
}
let Wash = sleep.before(function () {
console.log('洗脸')
})
Wash() // 洗脸 睡觉
Wash('我') // 洗脸 我睡觉

发布订阅模式

定义了对象间一种一对多的依赖关系,当目标对象 Subject 的状态发生改变时,所有依赖它的对象 Observer 都会得到通知。

一个目标者对象 Subject,拥有方法:添加 / 删除 / 通知 Observer;

多个观察者对象 Observer,拥有方法:接收 Subject 状态变更通知并处理;

目标对象 Subject 状态变更时,通知所有 Observer。

Subject 添加一系列 Observer, Subject 负责维护与这些 Observer 之间的联系,“你对我有兴趣,我更新就会通知你”。

作用:

  • 广泛应用于异步编程中(替代了传递回调函数)
  • 对象之间松散耦合的编写代码

代码实现:

文章作者: 青空
文章链接: https://gitee.com/AIR-ZRB/blog/2020/03/16/%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1%E6%A6%82%E5%BF%B5/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 青空
打赏
  • 微信
    微信
  • 支付寶
    支付寶