你不知道的javascript设计模式(五)----单例模式

前言

        前几章我们一直在为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中使用全局变量实现的方法,并且还总结了上一章的内容,设计函数的过程中要考虑这个函数的复用性,是否遵循开放-封闭原则,这一章还提到了单一职责原则,会在后面的章节专门说明
       小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!
       每天学习进步一点点,就是领先的开始。如果想继续提高,欢迎关注我,或者关注公众号”祯民讲前端“。大量前端技术文章,面试资料,技巧等助你更进一步!
在这里插入图片描述

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值