概念

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

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

实现思路

一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为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. ML:吴恩达 机器学习 课程笔记(Week7~8)

    Support Vector Machines Unsupervised Learning Dimensionality Reduction

  2. [Erlang-0016][aque_tcp] 一个 Erlang TCP 组件

    项目地址:https://github.com/liangjingyang/aque_tcp 欢迎任何形式的转载,但请务必注明出处:http://www.cnblogs.com/liangjingya ...

  3. Qt信号量QSemaphore(在线程里使用,结合生产者消费者的问题)

    Qt中的信号量是由QSemaphore类提供的,信号量可以理解为对互斥量功能的扩展,互斥量只能锁定一次而信号量可以获取多次,它可以用来保护一定数量的同种资源.acquire()函数用于获取n个资源,当 ...

  4. windows 下 php 实现在线预览附件(pdf)

    (写的有点啰嗦,具体的实现方法只是粗体和代码就够了) 给市场部门用dede做个cms,需要附件在线查看.公司有个系统(就叫develop_cms吧)是已经实现的,本以为很容易,不过是下一个插件然后把附 ...

  5. 浅入深出Vue:数据渲染

    今天来正式开始 vue的学习,首当其冲的当然是数据的渲染.毕竟数据就是拿来看的,看看如果使用 vue来展示数据. 为什么渲染 俗话说 "人靠衣装马靠鞍", 那咱们的代码就是得靠 U ...

  6. Centos6 samba服务配置

    1.在阿里虚拟机中配置包源  在ecs的 /etc/yum.repos.d 创建个 alios.repo,内容如下 [alios.$releasever.base.$basearch] name=al ...

  7. Azkaban —— 编译及部署

    一.Azkaban 源码编译 1.1 下载并解压 Azkaban 在3.0版本之后就不提供对应的安装包,需要自己下载源码进行编译. 下载所需版本的源码,Azkaban的源码托管在GitHub上,地址为 ...

  8. Java NIO 学习笔记(一)----概述,Channel/Buffer

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  9. POI 设置Excel单元格背景色(setFillForegroundColor)

    背景介绍:使用Java开发信息系统项目,项目中往往会涉及到报表管理部分,而Excel表格首当其冲称为最合适的选择,但是对单元格操作时对于设置单元格的背景颜色却很少提及,本文旨在方便单元格背景颜色设计. ...

  10. JVM结构的简单梳理

    #cnblogs_post_body img { width: 500px; height: auto; } JVM是什么 JVM的基本特性 JVM的流程结构 1. Java编译(Java Compi ...