设计模式之单例模式

文中内容均来自于曾探《JavaScript设计模式与开发实践》的学习笔记。

定义


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

使用场景:

  • 登录窗口;

  • 全局缓存;

  • 线程池;

  • 浏览器中的Window对象;

实现单例模式


面向对象的实现方式:

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( 'sven1' );
var b = Singleton.getInstance( 'sven2' );
alert ( a === b ); // true
​
//或者:
var Singleton = function( name ){
    this.name = name;
};
Singleton.prototype.getName = function(){
    alert ( this.name );
};
Singleton.getInstance = (function(){
    var instance = null;
    return function( name ){
        if ( !instance ){
            instance = new Singleton( name );
        }
        return instance;
    }
})();

透明的单例模式


面向对象的实现方式:

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( 'sven1' );
var b = new CreateDiv( 'sven2' );
alert ( a === b ); // true

用代理实现单例模式


面向对象的实现方式:

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( 'sven1' );
var b = new ProxySingletonCreateDiv( 'sven2' );
alert ( a === b );

JavaScript中的单例模式


全局变量不是单例模式,但是在JavaScript开发中,我们经常会把全局变量当成单例来使用。

如何降低全局变量带来的命名污染。

  • 使用命名空间

var MyApp = {};
MyApp.namespace = function( name ){
    var parts = name.split( '.' );
    var current = MyApp;
    for ( var i in parts ){
        if ( !current[ parts[ i ] ] ){
            current[ parts[ i ] ] = {};
        }
        current = current[ parts[ i ] ];
​
    }
};
MyApp.namespace( 'event' );
MyApp.namespace( 'dom.style' );
console.dir( MyApp );
// 上述代码等价于:
var MyApp = {
    event: {},
    dom: {
        style: {}
    }
};
  • 使用闭包封装私有变量

var user = (function(){
    var __name = 'sven',
    __age = 29;
    return {
        getUserInfo: function(){
            return __name + '-' + __age;
        }
    }
})();

惰性单例


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

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

通用的惰性单例


var getSingle = function( fn ){
    var result;
    return function(){
        return result || ( result = fn .apply(this, arguments ) );
    }
};
​
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';
};
​
//下面我们再试试创建唯一的iframe 用于动态加载第三方页面:
var createSingleIframe = getSingle( function(){
    var iframe = document.createElement ( 'iframe' );
    document.body.appendChild( iframe );
    return iframe;
});

参考资料


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值