深入理解 JavaScript 单例模式 (Singleton Pattern)
概念
单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。
核心:确保只有一个实例,并提供全局访问。
实现思路
一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为getIntance);当我们调用这个方法时,类持有的引用不为空则返回这个引用,如果为空须创建该类实例并将实例的引用赋予该类保持的引用;同时将该类的构造函数定义为私有方法,那么其他环境就无法通过调用该类的构造函数来实例化该类的对象,只能通过该类提供的静态方法得到该类唯一的实例。
实现 Java 语言中的单例模式
public class Singleton {
private static final Singleton {
private Singleton() { };
public static Singleton getInstance {
if (INSTANCE == null) {
synchronized(Singleton.class) {
if(INSTANCE = null) {
INSTANCE = new Singleton()
}
}
}
return INSTANCE;
}
}
}
实现 JavaScript 语言中的单例模式
let Singleton = function(name){
this.name = name;
}
Singleton.prototype.getName = function() {
console.log(this.name)
}
Singleton.getInstance = (function() {
let instance;
return function(name) {
if(instance) return instance;
return instance = new Singleton(name)
}
})()
let s1 = Singleton.getInstance('owen'); // Singleton {name: "owen"}
let s2 = Singleton.getInstance('guowen'); // Singleton.getInstance('guowen');
s1 === s2 // true
JavaScript中单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
应用
命名空间
使用命名空间可以降低全局变量带来的命名污染;
最简单的方法是对象字面量
const globalWeb = {
a() {},
b() {}
// ...
}
或者使用闭包
let Singleton = (function(){
let instance;
let init = function() {
let name = 'owen';
return {
name,
data(){
return {}
},
method:{ }
}
}
return {
getInstance() {
if(instance) return instance;
return instance = init()
}
}
}())
let app = Singleton.getInstance() // {name: "owen", data: ƒ, method: {…}}
惰性单例
惰性单例指在需要的时候才创建对象实例,在实现开发中非常有用,即目标对象只有在使用的时候才被创建,而不是页面加载好时创建。
模态框示例
点击一个按钮弹窗一个模态框,很明显页面是唯一的,一次不会弹窗多个模态框的情况
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>modal box</title>
<style>
* {
margin: 0;
padding:0;
}
html{
width:100%;
height:100%;
}
.Owen {
width:30%;
height:30%;
margin:10% auto;
}
#modal {
width:100%;
height:100%;
position:fixed;
left:0;
top:0;
background: rgba(0, 0, 0, 0.52);
display:none;
}
.main{
width:30%;
height:30%;
margin:10% auto;
text-align: center;
background-color: #b0e8ff;
}
</style>
</head>
<body>
<div class="Owen">
<button>Owen</button>
</div>
<div id="modal">
<div class="main">
<div>
我是弹框
</div>
</div>
</div>
</body>
<script>
window.onload = function(){
let openModal = document.querySelector("button")
let modal = document.querySelector("#modal")
openModal.addEventListener('click',function(){
modal.style.display = 'block'
})
}
</script>
</html>
第一种方法是在页面加载完成时创建好这个弹框,一开始就是隐藏的,只有点击按钮的时候才显示,这种方式有一个问题,就是我们进入页面,只是看看其他内容,不做任何操作;这样就造成资源浪费
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>modal box</title>
<style>
* {
margin: 0;
padding:0;
}
html{
width:100%;
height:100%;
}
.Owen {
width:30%;
height:30%;
margin:10% auto;
}
#modal {
width:100%;
height:100%;
position:fixed;
left:0;
top:0;
background: rgba(0, 0, 0, 0.52);
}
.main{
width:30%;
height:30%;
margin:10% auto;
padding:20px;
text-align: right;
background-color: #b0e8ff;
position:relative;
}
.main div {
text-align: center;
}
.main span {
display: inline-block;
padding:5px;
cursor:pointer;
}
</style>
</head>
<body>
<div class="Owen">
<button>点我</button>
</div>
</body>
<script>
window.onload = function(){
init()
}
function init() {
let openModal = document.querySelector("button")
let createModal =( function() {
let flag;
// 生成 Modal 容器
let div = document.createElement('div')
div.id = "modal"
div.style.display = "none";
return function() {
if(flag) return div;
flag = true;
let fra = document.createDocumentFragment();
// 添加 Modal 内容
els = `<div class="main">
<span class="close">×</span>
<div>
我是弹框
</div>
</div>
`
div.innerHTML = els;
fra.appendChild(div)
document.body.appendChild(fra)
// 关闭 Modal
let close = document.querySelector('.close')
close.addEventListener('click',function(){
flag = false;
document.body.removeChild(div)
})
return div
}
}())
// 显示 Modal
openModal.addEventListener('click',function(){
createModal().style.display = "block";
})
}
</script>
</html>
第二种方法,只执行一次DOM的创建修改操作,不用频繁的创建和删除节点,提高资源利用率;
参考资料
《JavaScript设计模式与开发实践》
基维
深入理解 JavaScript 单例模式 (Singleton Pattern)的更多相关文章
- 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)
在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...
- 设计模式系列之单例模式(Singleton Pattern)——确保对象的唯一性
模式概述 模式定义 模式结构图 饿汉式单例与懒汉式单例 饿汉式单例 懒汉式单例 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 适用场景 说明:设计模式系列文章是读刘伟所著 ...
- 浅谈设计模式--单例模式(Singleton Pattern)
题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...
- 设计模式之单例模式(Singleton Pattern)
单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...
- 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)
原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...
- 【设计模式】单例模式 Singleton Pattern
通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance) 的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...
- 二十四种设计模式:单例模式(Singleton Pattern)
单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...
- Net设计模式实例之单例模式( Singleton Pattern)
一.单例模式简介(Brief Introduction) 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯 ...
- 深入设计模式(二)——单例模式(Singleton Pattern)
一.单例模式介绍 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯一实例,它就可以严格地控制客户怎样访问它 ...
- C# 单例模式(Singleton Pattern)(转SuagrMatl)
单例模式的定义: 确保一个类只有一个实例,并提供一个全局访问点. 首先实例大家应该都明白就是类生成对象的过程简单的就是String s=new String(),则s就是个实例. Q:如何只生成一个实 ...
随机推荐
- Qt 中C++ static_cast 和 reinterpret_cast的区别(static_cast是隐式类型转换,会有数据损失,reinterpret_cast是底层二进制转换,没有数据损失)
1.C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作.因此,被做为隐式类型转换使用.比如: int i; float f = 166.7f; i = static_cast ...
- 使用VS2010开发Qt程序的4点经验(QT4到QT5的升级,更改sln文件,切换工程使用的Qt库,在VS的Solution Explorer视图中建立文件夹)
导读 相比于Qt Creator,我更喜欢用VS2010来进行开发.虽然启动时间相对较慢,但是VS下强大的快捷键和丰富的插件,以及使用多年的经验,都让我觉得在开发过程中得心应手.其中最重要的一点是,有 ...
- Silverlight ItemsControl详细解析+解惑
Silverlight最强大的地方就在于定义控件了,Silverlight提供了非常灵活和高效的控件定义方式,几乎可以实现任何复杂的控件实现,对于快速开发应用程序有着重要的意义.在Silverligh ...
- python的内存分配
一.前言 大多数编译型语言,变量在使用前必须先声明,其中C语言更加苛刻:变量声明必须位于代码块最开始,且在任何其他语句之前.其他语言,想C++和java,允许“随时随地”声明变量,比如,变量声明可以在 ...
- Linux基础(二)
网卡的启动与关闭 ipup ens33 启动网卡 ifdown 关闭网卡 普通用户没有该权限 root用户,管理员,普通用户的权限 root 至高无上的 root用户所在的组是root组 管理员 ...
- SYN5605型 多通道时间间隔测量仪
SYN5605型 多通道时间间隔测量仪 时间间隔测量设备多通道时间间隔测量32路时间间隔测量仪使用说明视频链接; http://www.syn029.com/h-pd-80-0_310_6_-1. ...
- C语言实现常用排序算法——基数排序
#include<stdio.h> #include<math.h> #define SIZE 10 #define C_SIZE 20 /*行数稳定=10,切记!列数务必搞的 ...
- Python 爬虫从入门到进阶之路(七)
在之前的文章中我们一直用到的库是 urllib.request,该库已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Hum ...
- Zookeeper详解-工作流和leader选举(三)
一.工作流 一旦ZooKeeper集合启动,它将等待客户端连接.客户端将连接到ZooKeeper集合中的一个节点.它可以是leader或follower节点.一旦客户端被连接,节点将向特定客户端分配会 ...
- PhpStorm 配置 PHPUnit
配置说明 全局安装phpunit代码 composer global require phpunit/phpunit 该代码会自动保存在 /User/你的用户名/.composer/vendor/ph ...