概念

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

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

实现思路

一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为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. MacOS X编译OpenSceneGraph

    本文主要记录在MacOS X上编译OpenSceneGraph,方便日后查阅.所使用的环境如下: MacOS X 10.10 Yosemite XCode 6.3.2 CMake 3.3.0 Open ...

  2. SharePoint js操作原生的New/Edit表单

    列表的表单,有个类似的需求:在New需隐藏特定字段,Edit时显示. 默认是New/Edit表单的字段是一样,就算在Content type 是隐藏也是同时影响两个表单.   如何做到仅仅在New时隐 ...

  3. 【操作系统】elementary OS 和 deepin OS

    文章摘自:http://blog.sina.com.cn/s/blog_64fb59d90102x3xa.html 部分参考:https://bbs.deepin.org/forum.php?mod= ...

  4. VM中linux和windows主机进行串口通信

    最近在做关于AIS的内容.为了对AIS电文进行解码,串口收发. 数据有PC机模拟发送,为了调试方便,不用次次将程序放到开发板上运行,所以利用pc主机和虚拟机进行串口通信模拟该过程. 首先需要用到一个软 ...

  5. 条款10:令operator= 返回一个reference to *this

    关于赋值,可以写成连锁形式: int x, y, z; x = y = z = 15; //赋值连锁形式 赋值采用右结合律,故上述赋值被解析为: x = (y = (z = 15)); 为了实现连锁赋 ...

  6. java.lang.Integer cannot be cast to java.lang.String

    错误原因是类型转换! 说Integer 类型不能转成String类型.  解决办法: 将错误中的(String)强制转换类型修改为    object.toString() toString方法是Ja ...

  7. 警惕SAP项目被“中间商赚差价”

    前段时间某买卖二手车的广告特别火,里面有一句话叫“没有中间商赚差价”特别有说服力.同样在做SAP项目的过程中也是要警惕各种“中间商”赚差价. 正常的SAP项目的都是甲方和乙方两边签署合同合作实施,并不 ...

  8. Exceptionless(二) - 使用进阶

    Exceptionless(二) - 使用进阶 作者:markjiang7m2 原文地址:https://www.cnblogs.com/markjiang7m2/p/11100563.html 官网 ...

  9. Vue.js 是如何实现 MVVM 的?

    目录 框架到底为我们做了什么? 如何理解 MVVM ? 如何实现 MVVM - 以 Vue.js 为例 Vue 如何实现响应式 Vue 如何解析模板 Vue.js 运行机制 手写一个 Vue.js 框 ...

  10. 关于linux网卡消失的问题

    首先我也是一名学生,在学习的过程Linux的过程中,因为老师要求配置hadoop集群所以就匆匆忙忙的上手了,但是在配置网络的问题时遇到了网卡消失的问题 我在网上询问了许多的人,但是还是没有找到一个很好 ...