javascript设计模式之单例模式

栏目: 后端 · 发布时间: 5年前

内容简介:单例模式的定义为:简单来说,单例模式就是把一堆代码,放入到一个逻辑单元里面,可以通过单一的变量来访问。在我们最开始的写法中。我们通常会这样写:

什么是单例模式?

单例模式的定义为: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。

简单来说,单例模式就是把一堆代码,放入到一个逻辑单元里面,可以通过单一的变量来访问。 最大的好处就是封装代码,减少全局变量

为什么要使用单例模式?

在我们最开始的写法中。我们通常会这样写:

var btn = document.querySelector('#btn')
btn.onclick = function() {
    render()
}
function render() {
    console.log('render')
}复制代码

那么上面的代码有什么问题呢?

最主要的就是 全局变量多,难以维护

现在我们开始改进:

我们先把这一堆代码整合到一个对象里面,作为他的属性和方法,只保留一个全局变量。通过预留的入口启动。

var app = {
    btn: document.querySelector('#btn'),
    init: function() {
        this.bind()
    },
    bind: function() {
        var _this = this
        this.btn.onclick = function() {
            _this.render()
        }
    },
    render() {
        console.log('render jirengu.com')
    }
}
app.init()复制代码

虽然全局变量可以访问了,但是还是有一个缺点,app里面的属性和方法还是暴露了出来,可以直接用app访问。那我们接下来 使用闭包来将部分变量和方法隐藏起来。

var app = (function(){
   var btn = document.querySelector('#btn')
   function bind() {
       btn.onclick = function() {
           render()
       }
   }
   function render() {
       console.log('render jirengu.com')
   }

    return {
        init: function() {
            bind()
        }
    }
})()

app.init()复制代码

这种特殊的单例模式也叫 模块模式(module pattern)。

那么还有没有改进的方法呢?当然还有, 那就是在我们需要的时候在去创建,而不是立即创建实例 。代码如下:

var Singleton = (function(){
    var instance
    function createInstance() {
        var btn = document.querySelector('#btn')
        function bind() {
            btn.onclick = function() {
                render()
            }
        }
        function render() {
            console.log('render jirengu.com')
        }
        return {
            init: function() {
                bind()
            }
        }
    }
    return {
        getInstance: function() {
            if(!instance) {
                instance = createInstance()
            }
            return instance
        }
    }
})()

var app = Singleton.getInstance()
app.init()
复制代码

单例模式的应用场景

当我们访问一个网站的时候,比如访问以前的wepQQ(老版本),当我们点击时候,会有一个弹出层,来让我们去登陆。如下图:

javascript设计模式之单例模式

那么,这个唯一的窗口要如何创建呢?

由于我们知道只有当点击登陆按钮的时候,弹层才会出现,所以,我们可以在点击按钮后,惰性的创建一个div弹层。所以js代码如下:

var createLoginLayer = function(){
    var 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';
 };复制代码

可是这样的实现方法有一个缺点就是, 当我们每次点击登陆按钮时,都会创建一个新的DIV ,当我们点击关闭按钮时候,这个浮层又会消失。这样频繁的触发DOM操作, 创建和删除节点明显是不合理的,也是不必要的。

那么我们是否可以 设置一个变量来判断是否已经创建过浮层 呢?改进后代码如下:

var createLoginLayer = (function(){ 
    var 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';
};复制代码

这样便实现了只创建一个浮层需求。

可是上面的代码还有一个问题: 假如我还有其他的地方要创建单一的浮层,那么,我们要几乎将代码原封不动的写一遍,然后实现这个需求。

那么,我们需要把创建一个div和其他的iframe的公共部分给抽离出来: 用一个变量来标志是否创建过对象,如果是,则在下次直接返回这个已经创建好的对象 。

var obj;
if (!obj){
    obj = {};
}复制代码

那么我们将这些方法抽离出来,这些逻辑被封装在 getSingle 函数内部,创建对象的方法 fn 被当成参数动态传入 getSingle 函数,代码如下:

function getSingle(fn){
    var result;
    return result || (result = fn.call(this,arguments));

}复制代码

我们抽离代码后,便可以将创建的逻辑单独拿出来,放入getSingle,我们用result来保存fn的值,由于闭包,所以result永远不回被撤销。

所以代码可以如下所示:

var createLoginLayer = function(){
  var div = document.createElement( 'div' );
    div.innerHTML = '我是登录浮窗';
    div.style.display = 'none';
    document.body.appendChild( div );
    return div;
  };
var createSingleLoginLayer = getSingle(createLoginLayer);
  document.getElementById( 'loginBtn' ).onclick = function(){
   var loginLayer = createSingleLoginLayer();
   loginLayer.style.display = 'block';
};  

复制代码

总结

首先单例模式的核心是: 确保只有一个实例,并提供全局访问。

单例模式是一个简单而且使用的模式,而且惰性的单例模式,是我们可以完成需要的时候再去请求的功能,并且只创建唯一一个。

用好单例模型可以减少DOM的重复渲染,提高浏览器运行的效率。 

参考文献

JavaScript设计模式与开发实践


以上所述就是小编给大家介绍的《javascript设计模式之单例模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

最优化导论

最优化导论

Edwin K. P. Chong、Stanislaw H. Zak / 孙志强、白圣建、郑永斌、刘伟 / 电子工业出版社 / 2015-10 / 89.00

本书是一本关于最优化技术的入门教材,全书共分为四部分。第一部分是预备知识。第二部分主要介绍无约束的优化问题,并介绍线性方程的求解方法、神经网络方法和全局搜索方法。第三部分介绍线性优化问题,包括线性优化问题的模型、单纯形法、对偶理论以及一些非单纯形法,简单介绍了整数线性优化问题。第四部分介绍有约束非线性优化问题,包括纯等式约束下和不等式约束下的优化问题的最优性条件、凸优化问题、有约束非线性优化问题的......一起来看看 《最优化导论》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具