概念

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。

核心:确保只有一个实例,并提供全局访问。

实现思路

一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为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的创建修改操作,不用频繁的创建和删除节点,提高资源利用率;

Owen 个人博客

参考资料

《JavaScript设计模式与开发实践》

基维

大叔

深入理解 JavaScript 单例模式 (Singleton Pattern)的更多相关文章

  1. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  2. 设计模式系列之单例模式(Singleton Pattern)——确保对象的唯一性

    模式概述 模式定义 模式结构图 饿汉式单例与懒汉式单例 饿汉式单例 懒汉式单例 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 适用场景 说明:设计模式系列文章是读刘伟所著 ...

  3. 浅谈设计模式--单例模式(Singleton Pattern)

    题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...

  4. 设计模式之单例模式(Singleton Pattern)

    单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...

  5. 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)

    原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...

  6. 【设计模式】单例模式 Singleton Pattern

    通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance)  的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...

  7. 二十四种设计模式:单例模式(Singleton Pattern)

    单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...

  8. Net设计模式实例之单例模式( Singleton Pattern)

    一.单例模式简介(Brief Introduction) 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯 ...

  9. 深入设计模式(二)——单例模式(Singleton Pattern)

    一.单例模式介绍 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯一实例,它就可以严格地控制客户怎样访问它 ...

  10. C# 单例模式(Singleton Pattern)(转SuagrMatl)

    单例模式的定义: 确保一个类只有一个实例,并提供一个全局访问点. 首先实例大家应该都明白就是类生成对象的过程简单的就是String s=new String(),则s就是个实例. Q:如何只生成一个实 ...

随机推荐

  1. 常用json解析库比较及选择 fastjson & gson

    一.常用json解析库比较及选择 1.简介 fastjson和gson是目前比较常用的json解析库,并且现在我们项目代码中,也在使用这两个解析库. fastjson 是由阿里开发的,号称是处理jso ...

  2. Qt5下OpenGL程序的新写法

    在Qt5中,引入了QOpenGL*系列类,以取代Qt4时代的QGL*系列类. 下面是从Qt5例子中抠出的两种OpenGL程序模板,方便参考. 第一种写法: #ifndef TRIANGLEWINDOW ...

  3. 虚拟化代码博客 good

    推荐网站和博客地址 --------------------------------   虚拟化代码博客   QEMU大牛博客:qemu - 韋任的維基百科 http://people.cs.nctu ...

  4. qt获取网络ip地址的类

    最近在学习qt网络编程,基于tcp和udp协议. 看了一些别人的程序和qt4自带的例子,困扰我最大的问题就是获取ip的类,总结起来还挺多的. 主要介绍常用的QtNetwork Module中的QHos ...

  5. php生成html静态文件

    现在的动态网站存在很多性能上的弊端,seo优化会存在一定的瓶颈,现在将动态的网站代码转换为html静态文件,是浏览器通过html间接的读取动态网站源文件,这对其网站加载速度还是seo优化有着举足轻重的 ...

  6. spring常见十大异常

    一.找不到配置文件的异常 [plain] view plaincopy org.springframework.beans.factory.BeanDefinitionStoreException:  ...

  7. Spring Cloud Stream整合RabbitMQ

    简介 Spring Cloud Stream是一个构建消息驱动微服务的框架,应用程序通过input(相当于consumer).output(相当于producer)来与Spring Cloud Str ...

  8. 01 Django基础

    目录 一.什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对 ...

  9. spring 5.x 系列第22篇 —— spring 定时任务 (代码配置方式)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 关于任务的调度配置定义在ServletCo ...

  10. Electron为文件浏览器创建图标(三)

    在前面的文章中,请看之前文章,我们已经完成了使用 electron做文件浏览器这么一个应用,现在我们需要为应用创建图标操作.为应用创建图标以后,我们就可以从计算机中与其他应用区分开来,如果我们自己会做 ...