概念
保證一個(gè)類僅有一個(gè)一個(gè)實(shí)例归薛,并提供一個(gè)訪問它的全局訪問點(diǎn)
單例模式即一個(gè)類只能構(gòu)造出唯一實(shí)例,單例模式的意義在于共享匪蝙,唯一主籍,Redux/vuex中sre, jquery$ 或者業(yè)務(wù)場景中的購物車,登錄框都是單例模式應(yīng)用逛球。
任意一個(gè)網(wǎng)站千元,點(diǎn)擊登錄按鈕,只會(huì)彈出有且僅有一個(gè)登錄框颤绕,即使后面再點(diǎn)擊登錄按鈕幸海,也不會(huì)再彈出多一個(gè)彈框。這就是單例模式的典型應(yīng)用奥务。接下來我們實(shí)現(xiàn)它物独。為了注重單例模式的展示,我們把登錄框簡化吧
思路
新建一個(gè)對(duì)象判斷全局是否有該對(duì)象氯葬,如果有挡篓,就返回該對(duì)象,沒有就創(chuàng)建新的對(duì)象返回
es5
var Single = (function () {
// 通過閉包存儲(chǔ)一個(gè)instance實(shí)例帚称,以后的調(diào)用直接返回instance
var instance = null;
function Single(name) {
this.name = name;
}
return function (name) {
if (!instance) {
instance = new Single(name);
}
return instance;
}
})()
var a = new Single("hi");
var b = new Single("fsdfas");
console.log(a);
console.log(b);
console.log(a === b);//true
es6
class Single {
constructor(name) {
this.name = name;
this.instance = null;
}
static getInstance(name) {
if(!this.instance) {
this.instance = new Single(name);
}
return this.instance;
}
}
var a = Single.getInstance("hi");
var b = Single.getInstance("fsdfas");
console.log(a === b);//true
優(yōu)點(diǎn)
- 資源共享的情況下官研,避免由于資源操作時(shí)導(dǎo)致的性能或損耗等。如上述中的日志文件闯睹,應(yīng)用配置阀参。
- 控制資源的情況下,方便資源之間的互相通信瞻坝。如線程池等蛛壳。
彈框DEMO
- 傳統(tǒng)的面向?qū)ο?實(shí)現(xiàn)彈框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.modal {
width: 100px;
height: 100px;
border: 1px solid #f00;
position: absolute;
}
</style>
</head>
<body>
<button>彈框</button>
</body>
<script>
//傳統(tǒng)的面向?qū)ο? function Modal(options) {
this.offset = options.pos || 20;
this.index = count;
}
Modal.prototype.create = function() {
var oDiv = document.createElement("div");
oDiv.style.cssText = `
width: 100px;
height: 100px;
border: 1px solid #f00;
position: absolute;
`
oDiv.style.left = (++this.index)* this.offset + "px";
oDiv.style.top = (++this.index)* this.offset + "px";
oDiv.innerHTML =`第${this.index}個(gè)彈框`;
return oDiv;
}
//使用
var count = 1;//記錄彈框個(gè)數(shù)
document.querySelector("button").onclick = function() {
var oDiv = new Modal({
pos:20,
count: count
});
document.body.appendChild(oDiv.create());
count ++;
}
</script>
</html>
點(diǎn)擊多次效果:
- 使用單例模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.modal {
width: 100px;
height: 100px;
border: 1px solid #f00;
position: absolute;
}
</style>
</head>
<body>
<button>彈框</button>
</body>
<!-- <script src="./Modal"></script> -->
<script>
//傳統(tǒng)的面向?qū)ο? function Modal(options) {
this.offset = options.pos || 20;
this.index = count;
}
Modal.prototype.create = function() {
var oDiv = document.createElement("div");
oDiv.style.cssText = `
width: 100px;
height: 100px;
border: 1px solid #f00;
position: absolute;
`
oDiv.style.left = (this.index)* this.offset + "px";
oDiv.style.top = (this.index)* this.offset + "px";
oDiv.innerHTML =`第${this.index}個(gè)彈框`;
return oDiv;
}
//得到唯一的一個(gè)彈框的實(shí)例對(duì)象
Modal.getInstance = (function(options) {
var instance = null;
return function(options) {
if(!instance) {
instance = new Modal(options);
}
return instance;
}
})();
var count = 1;//記錄彈框個(gè)數(shù)
document.querySelector("button").onclick = function() {
var oDiv = Modal.getInstance({
pos:60,
count: count
})
document.body.appendChild(oDiv.create());
count ++;
}
</script>
</html>
點(diǎn)擊多次效果:
bug: 雖然表面效果實(shí)現(xiàn)了,但是dom結(jié)構(gòu)還是創(chuàng)建了節(jié)點(diǎn)所刀,只是第一個(gè)彈框一樣而已衙荐。
優(yōu)化后
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.modal {
width: 100px;
height: 100px;
border: 1px solid #f00;
position: absolute;
}
</style>
</head>
<body>
<button>彈框</button>
</body>
<!-- <script src="./Modal"></script> -->
<script>
//傳統(tǒng)的面向?qū)ο? function Modal(options) {
this.offset = options.pos || 20;
this.index = count;
}
Modal.prototype.create = function() {
var oDiv = document.createElement("div");
oDiv.style.cssText = `
width: 100px;
height: 100px;
border: 1px solid #f00;
position: absolute;
`
oDiv.style.left = (this.index)* this.offset + "px";
oDiv.style.top = (this.index)* this.offset + "px";
oDiv.innerHTML =`第${this.index}個(gè)彈框`;
return oDiv;
}
//把創(chuàng)建的彈框的邏輯寫到方法里面
Modal.getModal = (function(options) {
var instance = null; //記錄第一次的實(shí)例對(duì)象
var isExist = false;// 記錄是否創(chuàng)建過彈框
return function(options) {
if(!instance) {
instance = new Modal(options);
}
if(!isExist) {
document.body.appendChild(instance.create());
isExist = true;
}
}
})();
var count = 1;//記錄彈框個(gè)數(shù)
document.querySelector("button").onclick = function() {
Modal.getModal({
pos:60,
count: count
})
count ++;
}
</script>
</html>
點(diǎn)擊多次效果: