单例模式 - Singleton

145 阅读1分钟

一、定义

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

二、核心

确保只有一个实例,并提供全局访问

实例实现 

1. ES6实现单例

class Singleton {  
  constructor(name) {    
    this.name = name  
  }
  static getInstance(name) {    
    if (!Singleton.instance) {      
      Singleton.instance = new Singleton(name)    
    }    
    return Singleton.instance  
  }
 }

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

const s1 = new Singleton('张三');
const s2 = Singleton.getInstance('李四');
const s3 = Singleton.getInstance('王五');
s1.getName()  // ==> 张三
s2.getName()  // ==> 李四
s3.getName()  // ==> 李四

从上面的结果可以看出,通过静态的getInstance可以实现单例模式,然后仍然可以通过new的方式获得多个实例。所以需要对构造函数constructor进行改些:

  constructor(name) {
    // 每次new的时候判断是否存在实例,若存在则直接返回该实例    
    if (!Singleton.instance) {      
      this.name = name      
      Singleton.instance = this;    
    }    
   return Singleton.instance
    // return Signleton.getInstance() // 不能直接使用getInstance,否则会无限嵌套  
  }

再看结果:

const s1 = new Singleton('张三');
const s2 = Singleton.getInstance('李四');
const s3 = Singleton.getInstance('王五');
const s4 = new Singleton('赵六');
s1.getName()  // ==> 张三
s2.getName()  // ==> 张三
s3.getName()  // ==> 张三
s4.getName()  // ==> 张三

从结果说明,无论从new()方法,还是getInstance()方法,均只有一个示例。

2. ES5实现单例

function Person (name) {
  // this.name = name // 仍然存在ES6中new时多个实例的问题  
  if (!Person.instance) {    
    this.name = name    
    Person.instance = this;  
  }  
  return Person.instance
}

Person.prototype.getName = function() {  
  console.log(this.name)}
  Person.getInstance = (() => {  
    let instance = null;
    return function (name) {    
       if(!instance) {      
         instance = new Person(name)    
       }    
     return instance  
    }
 })()

const p0 = new Person('王五')
const p1 =  Person.getInstance('张三');
const p2 =  Person.getInstance('李四');
p0.getName() // ==> 王五
p1.getName() // ==> 王五
p2.getName() // ==> 王五

还可以抽离出通用的单例方法:

function getSingleton (fn) {  
    let instance = null;    
    return function () {    
       if (!instance) {      
           instance = fn.apply(this, arguments);    
       }    
       return instance  
    }
}

使用方法:

const PersonSingleton = getSingleton(function (name) {
  const mgs = new Person(name);
  return mgs;
})
PersonSingleton('张三').getName() // => 张三
PersonSingleton('李四').getName() // => 张三

跳转:设计模式目录