设计模式 -- 单例模式

2019-06-18 00:00:00

一个单例走天下。

前言

单例模式:一个类只有一个实例,并提供一个访问它的全局访问点。

使用该模式的优点主要是:

  • 避免全局函数和变量冲突
  • 利用闭包,隐藏实现细节,暴露常用 api

实现

接下来一步步推演单例模式实现的变化过程。

  • 最基本的单例模式

包含关联的属性的和方法

let singleton = {
    value: 'abc',
    getValue () {
        console.log(this.value)
    }
}

该方法的缺点是,所有的属性和方法都暴露给使用者,如果使用者删除或修改某些属性或方法,将极大可能造成大范围的影响。所以需要一些私有属性和方法,那么就变为下一步的形式。

  • 包含私有成员的单例模式
let singleton = (function () {
    let value = 'abc'
    
    return {
        getValue () {
            console.log(value)
        }
    }
})()

以上两种方式都直接创建了对象,如果该对象一直未被使用,那么将造成资源浪费,所以需改为在必要的时候才创建。

  • 惰性实例化
let singleton = (function () {
    let instance = null
    
    function init () {
        let value = 'abc'
        return {
            getValue () {
                console.log(value)
            }
        }
    }
    
    return function () {
        return instance || instance = init()
    }
})()

该方式多次获取实例均取得相同实例对象。

  • 采用 ES6 的 class改写
class Init {
    constructor (value) {
        this.value = value
    }
    
    static getInstance () {
        return this.instance || this.instance = new this('abc')
    }
    
    getValue () {
        console.log(this.value)
    }
}
  • 如果 class需要私有属性
let SingleClass = (function () {
    let privateName = 'private'
    
    return class {
        constructor (value) {
            this.value = value
        }
        
        static getInstance () {
            return this.instance || this.instance = new this('abc')
        }
        
        getPrivateName () {
            console.log('privateName =>', privateName)
        }
        
        getValue () {
            console.log(this.value)
        }
    }
})()

let singleton = SingleClass.getInstance()
总结

单例模式最大的好处在于对代码的组织作用,将相关的属性和方法放在一个不会被多次实例化的对象中,更方便维护。惰性单例在需要的时候才实例化,减少了不必要的内存消耗。闭包的使用,隐藏了实现细节,能防止一些错误的修改。

使用中,首要考虑采用 ES6的 class进行实现。

Gitalking ...

Markdown is supported

Be the first guy leaving a comment!