JS设计模式-单例模式
单例模式 1、普通构造函数 单例模式是指一个构造函数,无论new多少次,返回的都是同一个实例,比如alert,在我们使用的时候页面上只会有一个alert弹窗。先来看一个普通的构造函数
class Test {}
let a = new Test();
let b = new Test();
console.log(a === b); // false
通过函数属性构造单例
如果我们希望a,b是完全相等的应该怎样做?
可以在构造函数上增加一个instance属性来保存实例,并增加一个getInstance静态方法来获取实例。如果实例存在则直接返回,如果不存在则创建一个保存在instance属性中并返回。
class Single {
}
Single.getInstance = function () {
if (!this.instance) {
this.instance = new Single();
}
return this.instance
}
let a = Single.getInstance();
let b = Single.getInstance();
console.log(a === b);
解决参数问题
function Dialog(config) {
this.config = Object.assign({}, {
title: '温馨提示',
content: '我是内容区域'
}, config);
}
Dialog.getInstance = function (config) {
if (!this.instance) {
this.instance = new Dialog(config);
} else {
this.apply(this.instance, arguments)
}
return this.instance
}
Dialog.prototype.show = function () {
console.log(this.config.title);
}
let a = Dialog.getInstance({
title: '001标题',
content: '001内容'
});
a.show(); // 001标题
let b = Dialog.getInstance({
title: '002标题',
content: '002内容'
});
b.show(); // 002标题
console.log(a === b); // true
通过new操作符实现单例构造
let Dialog = (function () {
let instance;
function Dialog(config) {
if (!instance) {
instance = this;
}
instance.init(config);
return instance;
}
Dialog.prototype.init = function(config) {
this.config = Object.assign({}, {
title: '温馨提示',
content: '我是内容区域'
}, config);
}
Dialog.prototype.show = function () {
console.log(this.config.title);
}
return Dialog;
})();
let a =new Dialog({
title: '001标题',
content: '001内容'
});
a.show(); // 001标题
let b =new Dialog({
title: '002标题',
content: '002内容'
});
b.show(); // 002标题
console.log(a === b); // true
省略new操作符
let Dialog = (function () {
let instance;
function Dialog(config) {
instance = instance || (
this instanceof Dialog ? this : new Dialog(config)
)
instance.init(config);
return instance;
}
Dialog.prototype = {
constructor: Dialog,
init: function (config) {
this.config = Object.assign({}, {
title: '温馨提示',
content: '我是内容区域'
}, config);
},
show: function () {
console.log(this.config.title);
}
}
return Dialog;
})();
let a = Dialog({
title: '001标题',
content: '001内容'
});
a.show(); // 001标题
let b = Dialog({
title: '002标题',
content: '002内容'
});
b.show(); // 002标题
console.log(a === b); // true
惰性单例 这里以上面的弹窗为例,需要解决以下几个问题,动态创建dom且随便new多少次都只是创建一次,没有任何操作时是不需要创建dom的
/**
* 绑定事件
* @param element
* @param type
* @param handler
*/
const bindEvent = (element, type, handler) => {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, handler);
} else {
element['on' + type] = handler;
}
}
/**
* 单例模式
*/
let single = (function () {
let single;
return function (fn) {
return single || (single = fn.apply(this, arguments))
}
})();
/**
* 创建dom
* @returns {HTMLElement}
*/
function createDom() {
let dom = document.createElement('div');
dom.setAttribute('class', 'dialog-wrapper');
dom.style.display = 'none';
document.body.appendChild(dom);
return dom;
}
let Dialog = (function () {
let instance,
dom;
/**
* 创建弹窗
* @param config
* @returns {*}
* @constructor
*/
function Dialog(config) {
instance = instance || (
this instanceof Dialog ? this : new Dialog(config)
)
instance.init(config);
return instance;
}
Dialog.prototype = {
constructor: Dialog,
init: function (config) {
this.config = Object.assign({}, {
title: '温馨提示',
content: '我是内容区域',
width: 300,
height: 200
}, config);
dom = single(createDom);
dom.style.width = this.config.width + 'px';
dom.style.height = this.config.height + 'px';
dom.innerHTML = `<div class="dialog-header">
<span class="dialog-title">${this.config.title}</span>
<span class="close">关闭</span>
</div>
<div class="dialog-body">${this.config.content}</div>`;
this.eventBind();
},
eventBind: function () {
let closeDom = dom.getElementsByClassName('close')[0],
_self = this;
bindEvent(closeDom, 'click', function(e) {
_self.hide();
});
},
show: function () {
dom.style.display = 'block';
},
hide: function () {
dom.style.display = 'none';
}
}
return Dialog;
})();
let a = Dialog({
title: '001标题',
content: '001内容'
});
a.show();
let b = Dialog({
title: '002标题',
content: '002内容'
});
b.show();
console.log(a === b); // true
一个简单的弹窗就使用单例模式封装完成了
4 回复
没写完发毛线😒
问题好像有点多 正确的应该是这样吧
class Test {
static instance?: Test
static getInstance() {
if (!this.instance) {
this.instance = new Test()
}
return this.instance
}
}
@chenkai0520 谁说没有写完就不能发了,后面继续完善吖~~
@xingo4 还没有写完就下班了