Yapei Li

专注于前端领域

0%

js高阶5、单例模式,高级单例模式,工厂模式

在很久以前JS中都是值类型的,没有引用数据类型,如果创建的变量或者函数名和之前的一样,会把之前存储的值替换掉;

真实项目中团队协作开发,如果是这样来处理,经常会导致相互代码冲突:‘全局变量污染’‘全局变量冲突’

后来js中诞生了对象数据类型,解决了上面出现的污染或冲突问题:把描述同一件事物的特征或者属性,进行归纳汇总,以此来避免全局变量之间的冲突

单例设计模式(Singleton Pattern)

我们把对象数据类型实现 把描述同一件事物的特征或者属性,进行"分组、归类"(存储在同一堆内存空间中)以此来避免全局变量之间的冲突问题**的方式和思想叫做:单例设计模式**

在真实项目中,为了实现模块化开发或者团队协作开发,我们经常应用单例模式(一般业务逻辑部分的代码都是依托单例模式设计规划的)

1、表现形式:

singleton不仅仅是对象名了,在单例模式中,singleton称之为“命名空间(nameSpace)

1
2
3
4
5
//单例模式
//singleton不仅仅是对象名了,在单例模式中,singleton称之为“命名空间(nameSpace)”
var singleton={
xxx:xxx
}

把描述同一件事物的属性或者方法存放在同一个命名空间下,多个命名空间中的属性和方法是互不干扰的

2、作用

把描述同一件事物的特征或者属性,进行"分组、归类"(存储在同一堆内存空间中)因此避免了全局变量之间的冲突和污染

3、单例模式的由来

每一个命名空间都是JS中Object这个内置类的实例,而实例之间是相互独立互不干扰的,所以我们称它为“单例:单独的实例”

高级单例模式

1、在给命名空间赋值的时候,不是直接赋值一个对象,而是先执行匿名函数,形成一个不销毁的私有作用域(不销毁的栈内存),在这个私有作用域中创建一个堆内存,把堆内存地址赋值给命名空间

2、这种模式的好处:我们完全可以在这个不销毁的私有作用域中创造很多内容(变量或者函数),哪些需要供外面调取使用的,我们暴露到返回的对象中(模块化实现的一种思想)

基于js高阶编程技巧**惰性思想**来实现的单例模式,并且可以把一些常用的设计模式(例如:命令模式、发布订阅设计模式、promise设计模式等)融合进来,最后清晰的规划我们的业务逻辑代码,方便后期二次开发和维护,这种设计思想综合体就是**高级单例模式**,也是项目中最常应用的

发布订阅设计模式:更加清晰的规划,把一些事件,事先存储在事件池或者任务池当中,以后到达指令池的时候我们只要一通知就行了,这样的话我们以后就没必要写个方法再去里边改代码了

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//高级单例模式  基本表现形式
var searchModel=(function(){}
//不销毁的私有作用域(闭包)
function submit(){

}
return {
submit:submit
}
})()
searchModel.submit()

//命令模式 init是唯一入口
var searchModel=(function(){}
//不销毁的私有作用域(闭包)

function submit(){

}
function fn(){

}
return {
init:function(){
this.submit()
this.fn()
}
}
})()
searchModel.init()

//发布订阅模式
var searchModel=(function(){}
var $searchPlan=$.Callbacks();
function submit(){

}
$searchPlan.add(submit)

function fn(){

}
$searchPlan.add(fn)
return {
init:function(){
$searchPlan.fire();
}
}
})()
searchModel.init()

使用单例模式实现模块化开发

模块化开发:

1、在团队协作开发的时候,我们经常会把一个复杂的页面,按照具体功能划分成为几大块,然后分别去开发,这种模块划分的思想就是“模块化开发思想”

2、把各个板块之间公用的部分进行提取封装,后期再想实现这些功能,直接调取引用即可

真实项目中,我们可以使用单例模式(建议使用单例模式)来实现模块化开发

闭包方法实现模块化开发弊端:随着每个人暴露在全局下的方法越来越多还是存在变量冲突问题

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
32
33
34
35
36
//基于单例模式的命令模式
//公共模块
var utils=(function(){}
var getPos=function(){}
return {
getPos:getPos
}
})()

//搜索模块
var searchModel=(function(){}
var submit=function(){}
return {
init:function(){
submit() //调取自己模块的包
utils.getPos() //调取公共模块方法
},
submit:submit
}
})()
searchModel.init();

//天气模块
var weatherModel=(function(){}
var setWeather=function(){
searchModel.submit() //调取别人的方法
}
return {
init:function(){
setWeather()
},
setWeather:setWeather
}
})()
weatherModel.init()

工厂模式(Factory Pattern)

1、把实现相同功能的代码进行封装,以此来实现“批量生产具体对象”(后期想要这个功能,我们只需要执行函数即可)

2、“低耦合高内聚”:减少页面冗余代码,提高代码的重复使用

工厂模式解决了创建多个相似对象的问题,没有解决对象识别的问题(即怎样知道一个对象的类型)

其实就是函数封装

1
2
3
4
5
6
7
8
function createPerson(name,age){
var obj=new Object();
obj.name=name;
obj.age=age;
return obj;
}
var p1=createPerson('aaa',16)
var p2=createPerson('bbb',18)