Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript之单例模式 #18

Open
Jouryjc opened this issue Aug 18, 2018 · 0 comments
Open

Javascript之单例模式 #18

Jouryjc opened this issue Aug 18, 2018 · 0 comments

Comments

@Jouryjc
Copy link
Owner

Jouryjc commented Aug 18, 2018

定义

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式又名单体模式。

单例模式的要点有三个:

  • 某个类只能有一个实例;
  • 它必须自行创建这个实例;
  • 它必须自行向整个系统提供这个实例。

单例模式是一种常见的模式,也比较简单。比如线程池、全局缓存、浏览器的window对象等。

作用

减少反复创建和销毁相同对象的成本。

举例

要实现一个标准的单例模式不复杂,就是用一个变量instance来标志是否已经创建过对象,如果是则下次直接返回该类的实例。

var Singleton = function (name) {
    this.name = name;
    this.instance = null;
}

Singleton.prototype.getName = function () {
    console.log(this.name);
}

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

var a = Singleton.getInstance('jour01');
var b = Singleton.getInstance('jour02');

console.log(a === b);    // true

上面我们已经实现了单例模式,但是Singleton.getInstance这个写法很花里胡哨。这增加了不透明性,我们们必须知道这个类是单例类才能这么用。我们优化下这个实例,通过代理模式重写:

var Singleton = function (name) {
    this.name = name;
}

Singleton.prototype.getName = function () {
    console.log(this.name);
}

var ProxySingleton = (function () {
    var instance;
   
    return function (name) {
        if (!instance) {
            instance = new Singleton(name);
        }

        return instance;
    }
})();

var a = new ProxySingleton('jour01');
var b = new ProxySingleton('jour02');

console.log(a === b);    // true

JS中单例模式就更简单了:

var obj = {};

obj是个全局变量,也是单例对象。是独一无二的,且全局都可以访问。但这是很糟糕的写法,污染了全局空间,容易造成冲突。

惰性单例

惰性单例指的是在需要的时候才创建对象实例。下面通过实现一个登录弹窗来说明惰性单例的作用:

<html>
    <body>
        <button id="loginBtn">登录</button>
    </body>
</html>
var createLoginLayer = function () {
    var div = document.createElement('div');
    div.innerHTML = '登录窗口';
    div.style.display = 'none';
    document.body.appendChild(div);
    return div;
}

var proxySingletonLayer = (function () {
    var instance;
   
    return function () {
        if (!instance) {
            instance = createLoginLayer();
        }

        return instance;
    }
})();

document.getElementById('loginBtn').onclick = function () {
    var loginLayer = proxySingletonLayer();
    loginLayer.style.display = 'block';
}

优点

  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
  • 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。

缺点

  • 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
  • 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。

小结

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant