昨天開始學(xué)習(xí)js里的設(shè)計(jì)模式,這里特別推薦一本書《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》,這本書是騰訊前端大神寫的,講的非常好,有實(shí)際當(dāng)中的應(yīng)用場景,還有講了怎樣用,什么地兒用,這位森賽講的很好。
但是在閱讀當(dāng)中呢有一些地方還不太明白(我比較菜),然后又了了湯姆大叔的"深入理解JavaScript"這個(gè)系列博客,其中大叔有提到設(shè)計(jì)模式,讀起來比起前面提到這本書講的更好理解一些。
下面貼出我的筆記和代碼:
//單例模式
//一個(gè)類,只產(chǎn)生一個(gè)實(shí)例,而且可以全局訪問
//不透明的單例模式。 因?yàn)橛弥安恢浪@個(gè)類是個(gè)單例
var Singleton = function(name) {
this.name = name;
this.instance = null;
};
Singleton.prototype.getName = function() {
console.log('test');
};
Singleton.getInstance = function(name) {
if (!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
};
var a = Singleton.getInstance('sven1');
var b = Singleton.getInstance('sven2');
//這時(shí)候你去拿b的name 還會顯示sven1
//還可以這樣寫
var Singleton2 = function(name) {
this.name = name;
};
Singleton2.prototype.getName = function() {
console.log(this.name);
};
Singleton2.getInstance = (function() {
var instance = null;
return function (name) {
if (!instance) {
instance = new Singleton2(name);
}
return instance;
}
})();
//透明的單例.在頁面中創(chuàng)建唯一的一個(gè)節(jié)點(diǎn)
var CreateDiv = (function() {
var instance;
var CreateDiv = function (html) {
if (instance) {
return instance;
}
this.html = html;
this.init();
return instance = this;
};
CreateDiv.prototype.init = function() {
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.appendChild(div);
};
return CreateDiv;
})();
//和代理類結(jié)合,這樣可以很好完成復(fù)用
var CreateDiv2 = function(hmtl) {
this.html = html;
this.init();
};
CreateDiv2.prototype.init = function() {
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.appendChild(div);
};
var ProxySingletonCreateDiv = (function() {
var instance;
return function (html) {
// body...
if (!instance) {
instance = new CreateDiv2(html);
}
return instance;
}
})();
//這樣子搞就是跟方便一點(diǎn) 你可以用creatediv2這個(gè)類創(chuàng)建許多實(shí)例, 也可以可代理類結(jié)合
//搞出一個(gè)單例模式出來
//以上是傳統(tǒng)的單例實(shí)現(xiàn)方法,基于類的,但是因?yàn)閖s是class-free類型 語言(雖然es6添加了class這個(gè)概念)
//所以在JS開發(fā)環(huán)境中具體實(shí)現(xiàn)的單例模式還不太一樣
//最簡單的,可以這樣搞
var mySingleton = {
property1: "something",
property2: "something else",
method1: function () {
console.log('hello world');
}
};
//復(fù)雜一些的,可以拓展功能的
var mySingleton = function () {
/* 這里聲明私有變量和方法 */
var privateVariable = 'something private';
function showPrivate() {
console.log(privateVariable);
}
/* 公有變量和方法(可以訪問私有變量和方法) */
return {
publicMethod: function () {
showPrivate();
},
publicVar: 'the public can see this!'
};
};
var single = mySingleton();
single.publicMethod(); // 輸出 'something private'
console.log(single.publicVar); // 輸出 'the public can see this!'
//下面是惰性單例(需要的時(shí)候,再創(chuàng)建對象)的實(shí)現(xiàn)
//一個(gè)懸浮登陸框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>loginBtn</title>
</head>
<body>
<button id="loginBtn">登陸</button>
</body>
<script>
var createLoginLayer = (function() {
var div;
return function () {
if (!div) {
var div = document.createElement('div');
div.innerHTML = "登陸浮窗";
div.style.display = 'none';
document.body.appendChild(div);
}
return div;
}
})();
document.getElementById('loginBtn').onclick = function () {
var loginLayer = createLoginLayer();
loginLayer.style.display = 'block';
};
</script>
</html>
//以上仍不是通用的惰性單例模式
//see? 我們抽出惰性單例通用的邏輯
var obj;
if ( !obj ){
obj = xxx;
}
//我們可以把它抽象成一個(gè)函數(shù)
//fn是創(chuàng)建對象的方法,result保存對象,因?yàn)樗陂]包中 所以不會被銷毀。
//getSingleton 這個(gè)方法來管理單例
var getSingleton = function(fn) {
var result;
return function () {
return function() {
return result||(result = fn.apply(this, [arguments]));
};
}
};
var createLoginLayer = function() {
var div = document.createElement('div');
div.innerHTML = '我是登錄浮窗';
div.style.display = 'none';
document.body.appendChild(div);
return div;
};
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById('loginBtn').onclick = function() {
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = 'block';
};
以上就是單例的筆記與總結(jié)。