设计模式系列-1.单例模式

设计模式系列-1.单例模式

为什么要强调设计模式..太重要了这玩意..有的时候反思我为什么看不懂大神写的代码..一方面就是不懂设计模式..或者反应不出来这玩意到底是什么设计模式

大部分资料出自网络..提纲按照汤姆大叔的来

单例模式

一个类只有一个实例

一般定义类: 缺点是暴露属性
1
2
3
4
5
6
7
var obj = {
property: '1',
property_:'2',
show: function(){
return this.property + this.property_;
}
}
闭包改进
1
2
3
4
5
6
7
8
9
var getObj  = function(salary){
var salary = salary || 0;
return {
publicVar : '1',
getSalary: function(){
return salary;
}
}
}
再改进

上面的代码很不错了,但如果我们想做到只有在使用的时候才初始化,那该如何做呢?为了节约资源的目的,我们可以另外一个构造函数里来初始化这些代码,如下:

IIFE 初始化形式
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
var mySingleton_1 = (function(salary){
var instance; // 判断是否已经形成单例
var init = function(){ // 单例初始化
return {
public_var: 'public',
getSalary: function(){
return salary + this.public_var;
}
}
}

return {
getInstance:function(){
if(!instance){
instance = init(salary);
}
return instance;
}
}
})(5000);

console.log(mySingleton_1.getInstance().getSalary()); //5000

mySingleton_1.getInstance().public_var = 2;
console.log(mySingleton_1.getInstance().getSalary()); //5002

console.log(mySingleton_1.getInstance() === mySingleton_1.getInstance()); // true
别的方法实现单例 new构造函数形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 其他方法

function Single(a, b){
if(Single.instance){
return Single.instance;
}
var var_1 = a || 0;
var var_2 = b || 0;
this.getVar = function(){ // 想暴露的用this定义成属性, 不想暴露的写在变量里闭包用属性方法去访问
return var_1 + var_2;
}
Single.instance = this;
}

var u1 = new Single(1, 2);
var u2 = new Single();
console.log(u1 === u2); // true
console.log(u1.getVar(), u2.getVar()) // 3 3;

不足在哪? 单例不受保护…u1, u2之间可以篡改Single.instance

知识无处不相通..再复习一下new 的过程

参考

1
2
var F = function(){}
var A = new F();

过程
  1. 新建一个对象
1
var instance = new Object();
  1. 设置原型链
1
instance.__proto__= F.prototype;
  1. 让F中的this指向instance,执行F的函数体.. call or apply的过程

  2. 判断F的返回值
    如果是值类型,就丢弃它,还是返回instance。
    如果是引用类型(包括返回this),就返回这个引用类型的对象,替换掉instance

故可以模拟new
1
2
3
4
5
6
7
var newF = function(...rest){
var obj = {}
obj.__proto__ = F.prototype;//绑定F的原型
F.apply(obj, ...rest); // 或者不用rest
F.apply(obj, Array.prototype.slice.call(arguments, 1)) // 在此注意arguments是类数组...只能Array.prototype.slice.call(arguments, 1)
return obj;
}

但是这样有个问题…instance被夹在Single属性里了…

再改进…重写构造函数 缓存的实例不被夹在构造函数里了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 // 改进 重写构造函数
var Single_ = function(a, b){
instance = this;
var var_1 = a || 0;
var var_2 = b || 0;

this.getVar = function(){
return var_1 + var_2;
}

Single_ = function(){
return instance;
}
}

var u1 = new Single_(6, 6);
var u2 = new Single_();

console.log(u1 === u2);

console.log(u1.getVar(), u2.getVar());