IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> JavaScript设计模式 - 单例模式 -> 正文阅读

[JavaScript知识库]JavaScript设计模式 - 单例模式

1. 单例模式的简单理解

介绍:保证一个类仅有一个实例,并提供一个访问他的全局访问点

实现一个标准的单例模式:用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象

使用场景:当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论点击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就可以使用单例模式来实现

注意:全局变量不是单例模式!!!
全局变量存在很多的问题,容易造成命名空间的污染,解决方法

  1. 使用命名空间
  2. 使用闭包封装私有变量

2. 实现单例模式

	let Singleton = function(name) {
            this.name = name
            this.instance = null
        }

        Singleton.prototype.getName = function() {
            console.log(this.name)
        }

        Singleton.getInstance = function(name) {
            if(!this.instance) {
                this.instance = new Singleton(name)
            }
            return this.instance
        }

        const a = Singleton.getInstance('test1')
        const b = Singleton.getInstance('test2')

        console.log(a === b)

通过Singleton.getInstance 来获取Singleton类的唯一对象,这种方法相对简单,但是有一个问题,就是增加了这个类的“不透明性”,Singleton类的使用者必须知道这是一个单例类,跟以往通过new XXX的方式获取对象不同,这里偏要使用Singleton.getInstance来获取对象

3. 透明的单例模式

 	let CreateDiv = (function() {
            let instance
            let CreateDiv = function(html) {
                if(instance) {
                    return instance
                }
                this.html = html
                this.init()
                return instance = this
            }
            CreateDiv.prototype.init = function() {
                let div = document.createElement('div')
                div.innerHTML = this.html
                document.body.appendChild(div)
            }
            return CreateDiv
        })()

        const diva = new CreateDiv('div1')
        const divb = new CreateDiv('div2')

        console.log(diva, diva === divb)

缺点 为了把instance封装起来,使用了自执行函数和闭包,并且让匿名函数返回真正的Singleton构造方法,增加了程序的复杂度,阅读起来也不舒服

CreateDiv 的构造函数做了两件事情

  1. 创建对象和执行初始化init方法
  2. 保证只有一个对象

4. 用代理实现单例模式

let CreateDiv = function(html) {
            this.html = html
            this.init()
        }
        CreateDiv.prototype.init = function() {
            let div = document.createElement('div')
            div.innerHTML = this.html
            document.body.appendChild(div)
        }
        // 引入代理类 ProxySingletonCreateDiv
        const ProxySingletonCreateDiv = (function() {
            let instance = null
            return function(html) {
                if(!instance) {
                    instance = new CreateDiv(html)
                }
                return instance
            }
        })()

        const proxy1 = new ProxySingletonCreateDiv('test1')
        const proxy2 = new ProxySingletonCreateDiv('test2')
        console.log(proxy1 === proxy2)

5. 惰性单例

惰性单例指的是在需要的时候才创建对象实例

5.1 通用的惰性单例

const createLoginLayer = (function() {
            let div
            return function() {
                if(!div) {
                    div = document.createElement('div')
                    div.innerHTML = '登录弹窗'
                    div.style.display = 'none'
                    document.body.appendChild(div)
                }
                return div
            }
        })()
        document.getElementById('loginBtn').onclick = function() {
            var loginLayer = createLoginLayer()
            loginLayer.style.display = 'block'
        }

存在的问题

  1. 违反单一职责原则,创建对象和管理单例逻辑都放在createLoginLayer对象内部
  2. 如果下次需要创建页面中唯一的iframe,或者script标签,用来跨域请求数据,就必须得如法炮制,把createLoginLayer函数几乎照抄一遍

5.2 优化后

const getSingle = function(fn) {
            let result
            return function() {
                return result || (result = fn.apply(this, arguments))
            }
        }
        const createLoginLayer = function() {
            let div = document.createElement('div')
            div.innerHTML = '登录弹窗'
            div.style.display = 'none'
            document.body.appendChild(div)
            return div
        }

        const createSingleLoginLayger = getSingle(createLoginLayer)

        document.getElementById('loginBtn').onclick = function() {
            var loginLayer = createSingleLoginLayger()
            loginLayer.style.display = 'block'
        }

在这个例子中,我们把创建实例对象的职责和管理单例的职责分别放置在两个方法里面,这两个方法可以独立变化而互不影响,当她们连接在一起的时候,就完成了创建唯一实例对象的功能

6. 总结

单例模式是一种特别简答但是非常实用的模式,特别是惰性单例模式,在适合的时候才创建对象,并且只创建唯一一个,更主要的是,创建对象和管理单例的职责分布在两个不同的方法中,这两个方法组合起来才具有单例模式的威立

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-16 18:44:30  更:2021-11-16 18:46:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 16:54:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码