javascript设计模式之单体模式学习笔记
发布时间 - 2026-01-10 23:04:26 点击率:次单体模式提供了一种将代码组织为一个逻辑单元的手段,这个逻辑单元中的代码可以通过单一变量进行访问。

单体模式的优点是:
- 可以用来划分命名空间,减少全局变量的数量。
- 使用单体模式可以使代码组织的更为一致,使代码容易阅读和维护。
- 可以被实例化,且实例化一次。
什么是单体模式?单体模式是一个用来划分命名空间并将一批属性和方法组织在一起的对象,如果它可以被实例化,那么它只能被实例化一次。
但是并非所有的对象字面量都是单体,比如说模拟数组或容纳数据的话,那么它就不是单体,但是如果是组织一批相关的属性和方法在一起的话,那么它有可能是单体模式,所以这需要看开发者编写代码的意图;
下面我们来看看定义一个对象字面量(结构类似于单体模式)的基本结构如下:
// 对象字面量
var Singleton = {
attr1: 1,
attr2: 2,
method1: function(){
return this.attr1;
},
method2: function(){
return this.attr2;
}
};
如上面只是简单的字面量结构,上面的所有成员变量都是通过Singleton来访问的,但是它并不是单体模式;因为单体模式还有一个更重要的特点,就是可以仅被实例化一次,上面的只是不能被实例化的一个类,因此不是单体模式;对象字面量是用来创建单体模式的方法之一;
使用单体模式的结构如下demo
我们明白的是单体模式如果有实例化的话,那么只实例化一次,要实现一个单体模式的话,我们无非就是使用一个变量来标识该类是否被实例化,如果未被实例化的话,那么我们可以实例化一次,否则的话,直接返回已经被实例化的对象。
如下代码是单体模式的基本结构:
// 单体模式
var Singleton = function(name){
this.name = name;
this.instance = null;
};
Singleton.prototype.getName = function(){
return this.name;
}
// 获取实例对象
function getInstance(name) {
if(!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
}
// 测试单体模式的实例
var a = getInstance("aa");
var b = getInstance("bb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的 console.log(a === b); // true
由于单体模式只实例化一次,因此第一次调用,返回的是a实例对象,当我们继续调用的时候,b的实例就是a的实例,因此下面都是打印的是aa;
console.log(a.getName());// aa console.log(b.getName());// aa
上面的封装单体模式也可以改成如下结构写法:
// 单体模式
var Singleton = function(name){
this.name = name;
};
Singleton.prototype.getName = function(){
return this.name;
}
// 获取实例对象
var getInstance = (function() {
var instance = null;
return function(name) {
if(!instance) {
instance = new Singleton(name);
}
return instance;
}
})();
// 测试单体模式的实例
var a = getInstance("aa");
var b = getInstance("bb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的
console.log(a === b); // true
console.log(a.getName());// aa
console.log(b.getName());// aa
理解使用代理实现单列模式的好处
比如我现在页面上需要创建一个div的元素,那么我们肯定需要有一个创建div的函数,而现在我只需要这个函数只负责创建div元素,其他的它不想管,也就是想实现单一职责原则,就好比淘宝的kissy一样,一开始的时候他们定义kissy只做一件事,并且把这件事做好,具体的单体模式中的实例化类的事情交给代理函数去处理,这样做的好处是具体的业务逻辑分开了,代理只管代理的业务逻辑,在这里代理的作用是实例化对象,并且只实例化一次; 创建div代码只管创建div,其他的不管;如下代码:
// 单体模式
var CreateDiv = function(html) {
this.html = html;
this.init();
}
CreateDiv.prototype.init = function(){
var div = document.createElement("div");
div.innerHTML = this.html;
document.body.appendChild(div);
};
// 代理实现单体模式
var ProxyMode = (function(){
var instance;
return function(html) {
if(!instance) {
instance = new CreateDiv("我来测试下");
}
return instance;
}
})();
var a = new ProxyMode("aaa");
var b = new ProxyMode("bbb");
console.log(a===b);// true
理解使用单体模式来实现弹窗的基本原理
下面我们继续来使用单体模式来实现一个弹窗的demo;我们先不讨论使用单体模式来实现,我们想下我们平时是怎么编写代码来实现弹窗效果的; 比如我们有一个弹窗,默认的情况下肯定是隐藏的,当我点击的时候,它需要显示出来;如下编写代码:
// 实现弹窗
var createWindow = function(){
var div = document.createElement("div");
div.innerHTML = "我是弹窗内容";
div.style.display = 'none';
document.body.appendChild('div');
return div;
};
document.getElementById("Id").onclick = function(){
// 点击后先创建一个div元素
var win = createWindow();
win.style.display = "block";
}
如上的代码;大家可以看看,有明显的缺点,比如我点击一个元素需要创建一个div,我点击第二个元素又会创建一次div,我们频繁的点击某某元素,他们会频繁的创建div的元素,虽然当我们点击关闭的时候可以移除弹出代码,但是呢我们频繁的创建和删除并不好,特别对于性能会有很大的影响,对DOM频繁的操作会引起重绘等,从而影响性能;因此这是非常不好的习惯;我们现在可以使用单体模式来实现弹窗效果,我们只实例化一次就可以了;如下代码:
// 实现单体模式弹窗
var createWindow = (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("Id").onclick = function(){
// 点击后先创建一个div元素
var win = createWindow();
win.style.display = "block";
}
理解编写通用的单体模式
上面的弹窗的代码虽然完成了使用单体模式创建弹窗效果,但是代码并不通用,比如上面是完成弹窗的代码,假如我们以后需要在页面中一个iframe呢?我们是不是需要重新写一套创建iframe的代码呢?比如如下创建iframe:
var createIframe = (function(){
var iframe;
return function(){
if(!iframe) {
iframe = document.createElement("iframe");
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
return iframe;
};
})();
我们看到如上代码,创建div的代码和创建iframe代码很类似,我们现在可以考虑把通用的代码分离出来,使代码变成完全抽象,我们现在可以编写一套代码封装在getInstance函数内,如下代码:
var getInstance = function(fn) {
var result;
return function(){
return result || (result = fn.call(this,arguments));
}
};
如上代码:我们使用一个参数fn传递进去,如果有result这个实例的话,直接返回,否则的话,当前的getInstance函数调用fn这个函数,是this指针指向与这个fn这个函数;之后返回被保存在result里面;现在我们可以传递一个函数进去,不管他是创建div也好,还是创建iframe也好,总之如果是这种的话,都可以使用getInstance来获取他们的实例对象;
如下测试创建iframe和创建div的代码如下:
// 创建div
var createWindow = function(){
var div = document.createElement("div");
div.innerHTML = "我是弹窗内容";
div.style.display = 'none';
document.body.appendChild(div);
return div;
};
// 创建iframe
var createIframe = function(){
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
return iframe;
};
// 获取实例的封装代码
var getInstance = function(fn) {
var result;
return function(){
return result || (result = fn.call(this,arguments));
}
};
// 测试创建div
var createSingleDiv = getInstance(createWindow);
document.getElementById("Id").onclick = function(){
var win = createSingleDiv();
win.style.display = "block";
};
// 测试创建iframe
var createSingleIframe = getInstance(createIframe);
document.getElementById("Id").onclick = function(){
var win = createSingleIframe();
win.src = "http://www.jb51.com";
};
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# js
# 设计模式
# 单体模式
# 轻松掌握JavaScript中介者模式
# 学习JavaScript设计模式之中介者模式
# 深入理解JavaScript系列(36):设计模式之中介者模式详解
# javascript设计模式之中介者模式Mediator
# Javascript 模式实例 中介者模式
# Javascript 中介者模式实例
# javascript设计模式之模块模式学习笔记
# javascript设计模式之策略模式学习笔记
# Javascript设计模式之装饰者模式详解篇
# javascript设计模式之中介者模式学习笔记
# 来实现
# 的是
# 都是
# 我是
# 创建一个
# 我们现在
# 其他的
# 我们可以
# 可以使用
# 当我们
# 窗内
# 有一个
# 是一个
# 这是
# 他们的
# 在这里
# 会有
# 他是
# 有可能
# 我现在
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
微信小程序 require机制详解及实例代码
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
Laravel怎么导出Excel文件_Laravel Excel插件使用教程
如何基于云服务器快速搭建网站及云盘系统?
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
如何在局域网内绑定自建网站域名?
Laravel如何为API编写文档_Laravel API文档生成与维护方法
JS弹性运动实现方法分析
如何在香港服务器上快速搭建免备案网站?
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
海南网站制作公司有哪些,海口网是哪家的?
html5如何实现懒加载图片_ intersectionobserver api用法【教程】
Linux系统命令中tree命令详解
php打包exe后无法访问网络共享_共享权限设置方法【教程】
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
如何快速辨别茅台真假?关键步骤解析
简单实现Android验证码
专业商城网站制作公司有哪些,pi商城官网是哪个?
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
MySQL查询结果复制到新表的方法(更新、插入)
Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
Android使用GridView实现日历的简单功能
Laravel如何使用Sanctum进行API认证?(SPA实战)
PythonWeb开发入门教程_Flask快速构建Web应用
重庆市网站制作公司,重庆招聘网站哪个好?
JavaScript数据类型有哪些_如何准确判断一个变量的类型
太平洋网站制作公司,网络用语太平洋是什么意思?
nodejs redis 发布订阅机制封装实现方法及实例代码
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
如何在阿里云高效完成企业建站全流程?
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
Laravel distinct去重查询_Laravel Eloquent去重方法
如何为不同团队 ID 动态生成多个独立按钮
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
如何用IIS7快速搭建并优化网站站点?
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
如何用VPS主机快速搭建个人网站?
如何批量查询域名的建站时间记录?
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
桂林网站制作公司有哪些,桂林马拉松怎么报名?
java ZXing生成二维码及条码实例分享
Laravel如何创建自定义Artisan命令?(代码示例)
Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】
微信推文制作网站有哪些,怎么做微信推文,急?
如何基于云服务器快速搭建个人网站?
谷歌Google入口永久地址_Google搜索引擎官网首页永久入口
小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像

