前言
前几章我们一直在为javascript设计模式的学习作一些准备,我们学习了原型编程,闭包,封装以及高阶函数等内容,从这一章节开始,我们将正式开始设计模式的学习,作为设计模式学习的第一章,我们将从最简单的设计模式,单例模式开始设计模式的相关学习
正文
单例模式的定义
保证一个类有且只有一个实例,并提供一个访问它的全局访问点
上面是对单例模式的官方定义,单例模式是一个很常见的设计模式,比如最常见的浏览器中的window对象,那些在实际业务中有且仅有一个的对象就适合单例模式来创建
实现单例模式
要实现单例模式并不难,无非就是用一个变量来标志当前对象是否已经被创建,如果没被创建就新建一个对象,如果已经创建就返回之前已经创建的对象
var Singleton = function (name) {
this.name = name;
this.instance = null;
}
Singleton.prototype.getName = function() {
console.log(this.name);
}
Singleton.prototype.getInstance = function(name) {
if (!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
}
var a = Singleton.getInstance('a');
var b = Singleton.getInstance('b');
console.log(a === b); // true;
javascript中的单例模式
上面的那种实现方式可能更多的是接近传统面向类编程的做法,但是javascript是一门无类语言,创建单例模式并不需要先定义一个类,再由这个类去定义对象,这样的做法无异于脱裤子放屁,我们只需要保证只是一个实例就是单例模式
在js开发中,我们经常把全局变量当作单例使用,当用这种方式创建的时候,全局变量便已经是独一无二的,但是这样的做法会有很多弊端,比如引起变量污染和覆盖的问题,在越大的项目中这个问题便会暴露得越明显。
在大型项目中为了解决这个问题,我们可以用专门的文件来存储这些单例对象,然后用接口把他们暴露出去,在对应的地方按需引入
// util.js
export singel = 1;
// main.js
import { singel } from './main.js';
惰性单例
惰性单例指的是在需要的时候才创建对象实例,惰性单例在单例模式中占很重要的地位,这个其实我们在文章开头就已经有所介绍,Singleton并不会在页面开始的时候就创建,而是在需要的时候主动调用getInstance时候才创建,不过我们也说了,javascript是一种无类语言,基于传统面向类的方式实现的单例模式对于javascript并不是最优选择。
假设我们需要写一个登陆的弹窗,并且在点击按钮以后,就弹出登陆的弹窗,这个是很适合使用单例模式来实现的,因为我们不会点登陆就一直创建新的登陆弹窗,弹窗只会有一个,这里我们基于js的全局变量去实现这个单例模式
var createLoginLayer = (function() {
var div;
return function () {
if (!div) {
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';
}
通用的惰性单例
上个部分虽然我们用变量去创建了一个单例模式,但是这个单例模式是违反了单一职责原则的,创建单例和管理单例都在一个函数里,而且这个函数的复用能力很差,如果下一次我们需要创建一个frame的单例,我们不得不把上面的代码复制出来一份改动中间的部分去实现单例
上一节我们在讲高阶函数的时候,讲过将业务中易变的部分封装为函数作为参数,保留不变的业务逻辑的程序设计思想,根据这个思想,其实我们可以提取出上面那个函数共同的部分
var getSingle = function(fn) {
var result;
return function() {
return result || (result = fn.apply(this, arguments));
}
}
接下来我们只需要把易变的那部分封装成函数再传入就可以了,这样如果有新的业务需求,我们并不需要更新getSingle方法,只需要封装新的业务函数传入单例模式就可以了,这样是符合开放-封闭原则的
小结
这一章我们介绍了单例模式,这是我们学习的第一个设计模式,这一章我们讲到了单例模式在基于类编程传统语言中的写法,以及在js中使用全局变量实现的方法,并且还总结了上一章的内容,设计函数的过程中要考虑这个函数的复用性,是否遵循开放-封闭原则,这一章还提到了单一职责原则,会在后面的章节专门说明
小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!
每天学习进步一点点,就是领先的开始。如果想继续提高,欢迎关注我,或者关注公众号”祯民讲前端“。大量前端技术文章,面试资料,技巧等助你更进一步!