概念

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

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

实现思路

一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为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. 关于CEdit控件的透明(重绘)

    摘自:http://www.jcwcn.com/html/VC/10_19_51_12.htm 做一个透明的Edit控件的主要问题是字符的输出,在Edit里输出的刷新有几个时机,一个是在接收到键盘或鼠 ...

  2. 孟岩:技术路线的选择重要但不具有决定性(什么是核心竞争力?是你独特的个性知识经验组合,正确的态度应该是着重于你要干的事情,然后认真把这件事情做好,然后融会贯通)good

    转自 http://blog.csdn.net/myan/article/details/3247071   孟岩 2008 年的文章,现在看来还是挺有启发, 送给大家,也送给自己. 最近微软在技术上 ...

  3. java泛型方法返回泛型结果

    public class Test { static HashMap<String, String> sMap = new HashMap<String, String>(); ...

  4. 使用Python爬取微信公众号文章并保存为PDF文件(解决图片不显示的问题)

    前言 第一次写博客,主要内容是爬取微信公众号的文章,将文章以PDF格式保存在本地. 爬取微信公众号文章(使用wechatsogou) 1.安装 pip install wechatsogou --up ...

  5. Element-ui安装之MessageBox详解

    1.首先根据官方文档进行Element-ui的安装,这个过程很简单(通过webpack-simple) 1) vue init webpack-simple element-ui 2) cd elem ...

  6. docker开启2376端口CA认证及IDEA中一键部署docker项目

    嘿,大家好,今天更新的内容是docker开启2376端口CA认证及IDEA中一键部署docker项目... 先看效果 我们可以通过idea一键部署docker项目,还以通过idea的控制台实时查看容器 ...

  7. Google Chrome浏览器插件入门开发

    --1. 在html文件中引用js 文件 --2.在Google Chrome中开发简单插件 1.首先,简单说明一下在html 中引用js 文件: 将kittenbook.html 和 kittenb ...

  8. 性能监控: SPF4J介绍

    1. 总体介绍 性能测试是一项在软件生命开发周期中总是被置于最后一环的活动.我们经常依靠 Java profilers 去帮助发现性能问题. 在这篇文章中,我们将会学习关于 Java 的简单性能测试框 ...

  9. 为什么建议大家使用 Linux 开发

    Linux 能用吗? 我身边还有些朋友对 linux 的印象似乎还停留在黑乎乎的命令行界面上.当我告诉他或者建议他使用 linux 时,会一脸惊讶的问我,那个怎么用(来开发或者日常使用)? Linux ...

  10. MagicBook屏幕频闪解决方案(Windows、MacOS)

    对于已经看到这篇文章的小伙伴们,就不解释何为PWM调光频闪了. MagicBook笔记本性价比高,但屏幕素质确实很一般,我们人眼看不出来的频闪,实际对眼睛损害很大,如图(需要设置快门参数,如1/400 ...