深入理解 JavaScript 单例模式 (Singleton Pattern)
程序员文章站
2022-06-27 21:54:30
概念 单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。 核心:确保只有一个实例,并提供全局访问。 实现思路 一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为 );当我们调用这个方法时,类持有的引用不为 ......
概念
单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。
核心:确保只有一个实例,并提供全局访问。
实现思路
一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常命名为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设计模式与开发实践》
基维
上一篇: 成语接龙-查找指定层数以内的成语