zoukankan      html  css  js  c++  java
  • js设计模式之单例模式

    1、定义

    保证一个类仅生成一个实例,并可以全局访问。

    2、应用范围

    单列模式应用非常广泛,有些场景下某些对象只需要一个,比如浏览器中的window对象,全局缓存对象等。在实际开发过程中应用也比较多,比如点击一个按钮产生一个登陆框,无论点击多少次都应该只在第一次产生这个登录框,而在后面点击N次也只能是复用这个登陆框,而非重新创建,这样的场景就可以使用单列模式来创建这个登陆框。

    3、实现一个简单的单例模式

    //简单版单列模式
    const Singleton = function (name) {
        this.name = name
        //这个instance来保存生成的实例
        this.instance = null
    }
    Singleton.prototype.getName = function () {
        return this.name
    }
    
    //静态方法
    Singleton.getInstance = function (name) {
        if (!this.instance){
            this.instance = new Singleton(name)
        }
        return this.instance
        
    }
    
    const A = Singleton.getInstance('A') 
    const B = Singleton.getInstance('B')
    console.log(A === B); //true
    console.log(A.getName()); //A
    console.log(B.getName()); //A
    

    要实现起来并不复杂,无非就是使用一个私有变量去保存已生成的实例,在下新建时判断是否存在这个实例,若存在直接返回,而不创建就OK了。

    4、透明版

    透明板也就要用new Constructor的形式创建对象,使用单例的类就像使用普通的类一样。
    下面我们使用闭包的形式来写一个单列类,并使用闭包的局部变量来保存已生成的实例。

    //透明板单列模式
    
    const Singleton = (function () {
        let instance = null
        //实现一个简单的类
        function createDiv(html){
            if (instance){
                return instance
            }
            this.html = html
    
            return instance = this
        }
        createDiv.prototype.init = function () {
            let div = document.createElement('div')
            div.innerHTML = this.html
            document.body.append(div)
        }
    
        return createDiv
    })()
    const A = new Singleton('A') 
    const B = new Singleton('B')
    console.log(A === B); //true
    

    5、代理版

    代理版本要实现的目标是将定义类的代码和管理单例的代码分开,实现更小粒度的划分,遵循单一职责原则

    const Singleton = function (name){
        this.name = name
    }
    const proxySingleton = (function () {
        let instance = null
        return function (name) {
            if (!instance){
                instance = new Singleton(name)
            }
            return instance
        }
    })()
    

    6、惰性单例

    前面写的例子都是基于'类'的单例模式,其目的在与创建一个唯一的由'类'生成的对象(这里的'类'指的是伪类,也就是我们把javascript中的构造函数当做其他传统语言中的类来进行理解,而其实javascript中是不存在类的的概念,所有对象都是构造函数基于原型克隆出来的,快扯到面向对象去了,这里就不多说了)
    理解惰性单例有如下两点
    1、而现在要理解的 "惰性单例"的概念,我们的思想不再局限于去实现一个全局唯一的由伪类生成的对象,我们维持的唯一单例可能是一个div,可能是一个列表,也自然可能是一个对象。
    2、另外要理解的是 '惰性'二字,也即 我们维持的单例在不需要的情况下是不会产生的,只有在需要的情况才会生成,其实这一点在第二节简单的单例模式里面就已经实现了,只有调用Singleton.getInstance才会生成,并且生成后会一直存在,等待复用
    一个例子:
    比如我们需要一个登陆框,而在页面上点击登陆就会弹出这个登陆框,无论多次点击生成的都应该是同一个DOM节点,而这个DOM节点只在第一次调用生成,后面点击登陆只会复用这个DOM节点。这里我们维持的唯一单例应该是登陆框的DOM节点,并且是惰性生成的,即永不点击登录,就永远不会生成该DOM节点。
    下面给出惰性单例的通用代码

    //惰性单例通用代码
    const getSingle = function (fn){
        let instance = null;
        return function (){
            return instance || (instance = fn.call(this, arguments))
        }
    }
    

    要实现上面维持登录框单例的例子, 这里说一下思路, fn的功能是产生登录框,并返回登录框的DOM,代码如下

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

    7、小结

    单例模式在开发过程中应用很广泛,特别是惰性单例,所以也是我们必须要掌握的点。然后要再啰嗦几句的就是关于,单一职责原则,开放封闭原则,最少知识原则等等面向对象的概念,无论是上面提到的还是没提到的,我们都需要有一定的了解,熟悉这些原则并应用于实际对于代码质量的提升肯定是巨大的。

  • 相关阅读:
    [个人]工作中的死亡陷阱
    [阮一峰]在软件开发中,一旦这些技术被取代,你的知识将变得毫无价值,因为它们大部分都是实施的细节。
    [原文 + 补充] 当你在浏览器中输入Google.com并且按下回车之后发生了什么?
    安全的知识点总结
    purge旧的ubuntu 的linux内核
    【个人】运维常识
    windows数字证书管理器
    在mobaxterm内连接deb使用lrzsz进行文件传输
    网络安全常见考试题
    linux deb系 rpm系 配置路由
  • 原文地址:https://www.cnblogs.com/chenlei987/p/11356439.html
Copyright © 2011-2022 走看看