惰性单例分析与学习

前言

本文基于你已经知道单例模式的要点,本文内容借鉴于《javascript设计模式与开发实践》这本书,做出了整理和一些思考。

建议阅读时间:10-15min

基础回顾

惰性单例是指需要的时候才创建对象实例。这种技术非常好用,而且在实际开发中被大范围的使用。

比如我们借鉴这种思想,实例对象是需要的时候才被创建而不是开始就创建,所以优化后的写法是这样的。

Singleton.getInstance = (function(){
    let instance = null;
    return function(name){
    if(!instance){
     instance = new Singleton(name)
    }
    return instance
    }
    }
)()

案例推进

下面的案例我们将结合页面中最常见的登录窗来进行说明。显然它符合单例的基本要求。

方案 一 :页面加载完成就创建好,然后通过点击事件控制其显示

备注 :为了简化语法,假设是在jq库下。

let  loginLayer = (function(){
    let  $div = $("<div></div>") ;
    $div.html('我是登录弹窗').css("display","none") ;
    $("body").append($div);
    return $div;
})()

$("#login").click(function(){
loginLayer.show();
})

优化1 :点击登录时才创建

上面的方法中,很显然是页面载入必然创建,而我们有些场景下是不需要登录弹窗的。

let  loginLayer = function(){
    let  $div = $("<div></div>") ;
    $div.html('我是登录弹窗').css("display","none") ;
    $("body").append($div);
    return $div;
}

$("#login").click(function(){
let loginLayer = loginLayer();
loginLayer.show();
})

优化2:按照上面的思路,重复创建销毁也不好

那么如何确认页面中是否已经有一个弹窗?这时候就需要一个全局变量来记录是否已经创建过。

let  loginLayer = (function(){
    let $div ;
    return function(){
    if(!$div){
        $div = $("<div></div>") ;
        $div.html('我是登录弹窗').css("display","none") ;
        $("body").append($div);
    }
    return $div;
    }
})()

$("#login").click(function(){
loginLayer.show();
})

抽离通用的单例模式

上面的思考中,我们完成了一个较好的单例模式的实践,但是其不具有良好的通用性,在下次创建一个iframe或者其他控件的时候,我们还是需要把它代码复制粘贴一遍。

所以我们看下是否有更好的思路,能够比较符合单一职责原则,创建对象和管理单例的逻辑都放到一个工具函数中管理?答案是肯定的。

首先分析单例的核心逻辑 :

let obj ;
if(!obj){
    obj = xxx;
}

实现单例函数的核心逻辑 :

let getSingle = function (fn){
 let result ;
 return function(){
    return result || (result = fn.apply(this,arguments)); 
 }
}

拓展

上述的通用函数可以用于各个场景,创建对象,绑定事件都可以。

比如 :只绑定一次的事件,不想因为每次追加事件重复绑定 。

原来的写法 需要借助jq one

let bindEvent = function(){
    $("div").one("click",function(){
    alert("click")
    })
}

let render = function (){
console.log("渲染数据");
bindEvent();
}

现在写法可以是 :

let bindEvent = getSingle(function(){
    $("div").click(function(){
    alert("click")
    })
    return true;
})

let render = function (){
console.log("渲染数据");
bindEvent();
}

总结

单例模式是一种简单但是非常实用的单例模式,特别是惰性单例,在需要的时候才创建,并且只创建一个,创建对象和管理实例放在两个不同方法中,这两个方法组合起来更能发挥单一职责和单例模式的作用。

友情链接

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Redis

Linux文件基本属性

在Linux中第一个字符代表这个文件是目录,文件或链接等等。 当为[d]则是目录。 当为[-]则是文件。 当是[l]则表示为链接文档。 当是[b]则表示为装置文...

970
来自专栏Golang语言社区

从websocket看go的应用

Go是互联网时代的通用编程语言。这样它就和命令行时代的C语言、图示界面时代的C++、以及互联网早期的Java语言等有不同的侧重。它强调保持自身的精巧和独立,从而...

3837
来自专栏IMWeb前端团队

xss漏洞挖掘思路

前言 xss作为江湖上一种常见的攻击手段,一直有广泛的使用。然而怎么样发现一个交互的地方是否会有xss漏洞呢?有一些通用的思路。一下就是思路的总结。 攻...

2977
来自专栏柠檬先生

你不知道的javaScript笔记(7)

异步:现在与将来   分块的程序     可以把JavaScript 程序写在单独的js 文件中,这个程序是由多个块组成的,这些块     中只有一个是现在执行...

2095
来自专栏FreeBuf

Oracle Advanced Support系统SQL注入漏洞挖掘经验分享

Oracle Advanced Support系统SQL注入漏洞分析 一年多前我在客户的一个外部环境中执行渗透测试,任何外部环境渗透测试的重要步骤之一就是挖掘出...

2977
来自专栏LeoXu的博客

[翻译]Android教程-保存数据-支持不同的平台版本

展示 平台版本 的仪表盘会基于浏览过 Google Play Store的设备数量有规律的更新,来展示运行每一种版本Android的激活设备的分布. 一般...

862
来自专栏xingoo, 一个梦想做发明家的程序员

基于RequireJS和JQuery的模块化编程——常见问题解析

由于js的代码逻辑越来越重,一个js文件可能会有上千行,十分不利于开发与维护。最近正在把逻辑很重的js拆分成模块,在一顿纠结是使用requirejs还是sea...

28810
来自专栏Samego开发资源

自动化运维之playbook

1743
来自专栏Golang语言社区

从websocket看go的应用

Go是互联网时代的通用编程语言。这样它就和命令行时代的C语言、图示界面时代的C++、以及互联网早期的Java语言等有不同的侧重。它强调保持自身的精巧和独立,从而...

3116
来自专栏Nian糕的私人厨房

WeChat 模块、模板与缓存

本次的系列博文的知识点讲解和代码,主要是来自于 七月老师 的书籍《微信小程序开发:入门与实践》,由个人总结并编写,关于更多微信小程序开发中的各项技能,以及常见问...

893

扫码关注云+社区

领取腾讯云代金券