专栏首页一路向前端JavaScript设计模式之单例模式

JavaScript设计模式之单例模式

单例模式是javascript中最简单也是最常用的模式之一。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式的特点:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

主要解决:一个全局使用的类频繁地创建与销毁。

怎么方便理解和记忆这种模式呢?

用一句话来记忆它就是:只有一个实例,有一个访问它的全局访问点,不能与new关键字一起使用。

那么从最简单的单例模式讲起,在javascript中一个对象字面量可以认为是一个最简单的单例类,以为它符合单例类的特点:只有一个实例,有一个全局访问点。

示例:

var Singleton = {
    attribute: true,
                
    method1: function(){
        //do something
    },
                
    method2: function(){
        //do something
    },    
};

Singleton.name = false;

上面示例的单例对象可以被修改,你可以随意添加属性和方法到对象中,又或者用delete运算符删除现有的成员。这实质上是违背了面向对象设计的一个原则:类可以被扩展,但不应该被修改。传统意义上的单例模式的定义是:单例类仅有一个实例,并提供一个访问它的全局访问点。上面的对象字面量不是一个实例化的类,所以严格来说,它不属于单例类。javascript不是一门传统的语言,所以不必一定要按传统的定义来限定它,我们将单例模式的定义更广义化:单例类是一组相关的属性和方法的集合,如果它能被实例化,那么它只能被实例化一次。这样对象字面量就符合单例模式的定义了。

拥有私有成员的单例类:

现在一个对象字面量就是javascript中最简单的单例类,那怎么实现单例类的私有成员呢?私有成员是对象内部独有的、其他对象无法访问的成员。在javascript中实现私有成员的方法是使用闭包:

var Singleton = (function(){
                
    var name = 'singleton';
                
    function getName(){
        alert(name);
    };
                
    return {
        attribute: true,
        getName: getName
    }
                
})();
            
Singleton.getName();  //singleton

上面的单例类实现的name成员的私有化。

单例的使用很广泛,一个最常见的例子就是网页中的弹框层,比如:登录框、提示框等等。

单例模式实现网页弹框:

var createDiv = (function(){
    div = document.createElement("div");
    div.innerHTML = '我是登录框';
    document.body.appendChild(div);
    return div;
})();

这种在页面一开始就创建DOM节点的方式有一个问题,也许我们进入一个网站只是随便看看,根本不需要进行登录操作,因为登录浮窗总是一开始就被创建好,那么很有可能将白白浪费一些 DOM节点。

惰性单例

惰性单例指的是在需要的时候才创建对象实例。惰性单例是单例模式的重点,这种技术在实 际开发中非常有用。

接下来我们使用惰性单例实现弹框,在用户点击登录按钮的时候才创建登录框:

var createDiv = function(){
    var div;

    return function(){
        if(!div){
            div = document.createElement("div");
            div.innerHTML = '我是登录框';
            document.body.appendChild(div);
        }
        return div;
    }
};
            
document.querySelector(".btn").onclick = createDiv();

通用的惰性单例

把上面创建div的过程提取出来,便得到一个通用的惰性单例模式:

var createSingleton = function(fn){
    var singleton;

    return function(){
        return singleton || (singleton = fn.apply(this, arguments));
    }
};

现在用通用的惰性单例改造下前面登录框的代码:

var createSingleton = function(fn){
    var singleton;
    
    return function(){
        return singleton || (singleton = fn.apply(this, arguments));
    }
};
            
function createDiv(){
    var div = document.createElement("div");
    div.innerHTML = '我是登录框';
    document.body.appendChild(div);
    return div;
};
            
var createDivSingleton = createSingleton(createDiv);
            
document.querySelector(".btn").onclick = function(){
    var div = createDivSingleton();
};

以上登录框应该一开始是隐藏状态的,这里为了能更好的理解单例模式,简化了这些细节。

单例模式的优缺点:

优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 移动端适配必须掌握的基本概念和适配方案

    随着技术的发展,移动设备越来越流行,并且不同设备间屏幕尺寸和屏幕像素的差异,移动端开发面临着多分辨率适配的问题。

    用户6167509
  • Vue项目使用CSS变量实现主题化

    主题化管理经常能在网站上看到,一般的思路都是将主题相关的CSS样式独立出来,在用户选择主题的时候加载相应的CSS样式文件。现在大部分浏览器都能很好的兼容CSS变...

    用户6167509
  • JavaScript设计模式之命令模式

    命令模式是将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对...

    用户6167509
  • 浮动元素margin-bottom失效 — IE6盒模型

    HTML5学堂:虽然IE6慢慢的退出市场了,但是还是有必要了解一些兼容问题,让自己的知识有一个更好的沉淀。margin-bottom的bug是容器div的 'z...

    HTML5学堂
  • 【H5 音乐播放实例】第二节 音乐详情页制作(2)1.2 音乐盒子区域

    剽悍一小兔
  • 惰性单例分析与学习

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

    RobinsonZhang
  • 2045: 双亲数

    2045: 双亲数 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 659  Solved: 302 [Sub...

    HansBug
  • 2301: [HAOI2011]Problem b

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MB Submit: 1737...

    HansBug
  • php实现登录页面的简单实例

    开始自然是从最简单的功能起步,我第一个任务选择了做一个登录操作,其实也没想象中那么简单。

    砸漏
  • 利用JQuery实现鼠标移动到图片上方的时候显示二维码,离开的时候不显示二维码

    今天给大家介绍一下怎样利用JQuery实现鼠标移动到图片上方的时候显示二维码,离开的时候不显示二维码的功能。 其实主要注意几点细节就可以轻松实现这样的功能了,第...

    林老师带你学编程

扫码关注云+社区

领取腾讯云代金券