守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 144|回复: 0

[技术资料] JavaScript设计模式----单例模式

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51756
    钢镚
    1422

    开源英雄守望者

    发表于 2016-8-3 12:12:52 | 显示全部楼层 |阅读模式
    来源:http://div.io/topic/1792


    声明:这个系列为阅读《JavaScript设计模式与开发实践》 ----曾探@著一书的读书笔记

    1.单例模式的特点和定义

    保证一个类仅有一个实例,并且提供一个访问它的全局访问点。

    2.传统面向对象语言的单例模式

    2.1传统语言描述的单例模式JavaScript实现

    var Singleton = function(name) {
        this.name = name;
        this.instance = null;
    };
    
    Singleton.prototype.getName = function() {
        alert(this.name);
    };
    
    Singleton.getInstance = function(name) {
        if (!this.instance) {
            this.instance = new Singleton(name);
        }
    
        return this.instance;
    };
    
    var a = Singleton.getInstance('seven1');
    var b = Singleton.getInstance('seven2');

    或者使用闭包的形式创建单例模式,同时符合惰性单例的特性

    var Singleton = function(name) {
        this.name = name;
    };
    
    Singleton.prototype.getName = function() {
        alert(this.name);
    };
    
    //利用闭包的特性创建单例,同时符合惰性单例的特性
    Singleton.getInstance = (function(name) {
        var instance;
        return function(name){
            if (!instance) {
                instance = new Singleton(name);
            }
        }
    })();
    
    var a = Singleton.getInstance('seven1');
    var b = Singleton.getInstance('seven2');
    
    console.log(a===b);   //true

    2.2透明的单例模式:

    //反面的单例模式的例子
    
    var CreateDiv = (function() {
        var instance;
        var CreateDiv = function(html) {
            if (instance) {
                return instance;
            }
            this.html = html;
            this.init();
            return instance = this;
        };
    
        CreateDiv.prototype.init = function() {
            var div = document.createElement('div');
            div.innerHTML = this.html;
            document.body.appendChild(div);
        }
    
        return CreateDiv;
    
    })();
    
    var a = new CreateDiv('seven1');
    var b = new CreateDiv('seven2');

    这样编写单例模式的缺点:

    为了把instance封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的Singleton构造方法,这增加了一些程序的复杂度。

    CreateDiv的构造函数负责了两件事情。1.创建对像和执行初始化init方法,第二是保证只有一个对象。不符合设计模式中的单一职责的概念。

    2.3引入代理实现单例模式

    var CreateDiv = function(html) {
        this.html = html;
        this.init();
    };
    
    CreateDiv.prototype.init = function() {
        var div = document.createElement('div');
        div.innerHTML = this.html;
        document.body.appendChild(div);
    }
    
    var ProxySingletonCreateDiv = (function() {
        var instance;
        return function(html) {
            if (!instance) {
                instance = new CreateDiv(html);
            }
            return instance;
        }
    })();
    
    var a = new ProxySingletonCreateDiv('seven1');
    var b = new ProxySingletonCreateDiv('seven2');

    引入代理实现单例模式的特点:

    我们负责管理单例的逻辑移到了代理类ProxySingletonCreateDiv中。这样一来,CreateDiv就变成了一个普通的类,他跟ProxySingletonCreateDiv组合起来可以达到单例模式的效果。

    3.JavaScript的单例模式对比

    在以上的代码中实现的单例模式都混入了传统面向对象语言的特点。而没有利用JavaScript这们语言的特点来实现一个单例模式。

    3.1惰性单例的例子

    概念描述:

    惰性单例指的是在需要的时候才创建对象的实例。惰性单例是单例模式的重点。

    var createLoginLayer=(function(){
        var div;
        return function(){
            if(!div){
                div=document.createElement('div');
                //创建一个登录框
            }
            return div;
        }
    })();
    
    document.getElementById('loginBtn').onclick=function(){
        var loginLayer=createLoginLayer();
        loginLayer.style.display='block';
    };

    代码解析:
    这里的对惰性单例的实现主要是只有单例了网页上的登录按钮,才会去创建,登录框的dom节点,并且只是创建一次。

    3.2通用的单例模式例子

    根据3.1的代码示例,我们的单例对像,但是并不是通用的,比如我们要创建的不是div而是iframe,那要怎么办呢?

    //获取单例
    var getSingle = function(fn){
        var result;
        return function (){
            return result || (result=fn.apply(this,arguments));
        };
    };
    
    //创建div登录框
    var createLoginLayer=function (){
        var div= document.createElement('div');
        div.innerHTML='我是登录框';
        document.body.appendChild(div);
        return div;
    };
    
    //创建iframe的dom节点
    var createIframe=function(){
        //创建irame节点的代码
    }
    
    var createSingleLoginLayer = getSingle(createLoginLayer);
    var createSingleIframe=getSingle(createIframe);
    
    var loginLayer1 = createSingleLoginLayer();
    var loginLayer2 = createSingleLoginLayer();
    
    var iframe1=createSingleIframe();
    var iframe2=createSingleIframe();
    
    console.log(loginLayer1 === loginLayer2);

    通用的单例创建的例子就是通过封装一个getSingle需要实现单例模式的对象。而且只是会只创建一次。因为使用了闭包的原因通过getSingle创建的result会在内存中一直存在不会销毁(除非页面关闭,或者手动释放)。

    总结:

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

    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2019-10-23 01:12 , Processed in 0.045254 second(s), 31 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表