前言
由于JS没有private
关键字,无法私有化构造器,所以下面代码无法限制:
class Person {
constructor() {
console.log("Person created");
}
}
const p1 = new Person();
const p2 = new Person();
console.log(p1 === p2); // false
实现
通过 Person.getInstance()
生成对象
class Person {
constructor() {
console.log("Person created");
}
static _ins = null
static getInstance() {
if (!this._ins) {
this._ins = new Person();
}
return this._ins;
}
}
const p1 = Person.getInstance();
const p2 = Person.getInstance();
console.log(p1 === p2);
但是如果创建对象时使用new Person()
,仍无法实现单例模式。
下面封装一个函数,把任何类传入,将其变为单例模式:
function singleton(className) {
let ins
return class {
constructor(...args) {
if (!ins) {
ins = new className(...args)
}
return ins
}
}
}
class Person {
constructor() {
console.log("Person created");
}
}
// const p1 = new Person();
// const p2 = new Person();
const SingletonPerson = singleton(Person);
const p1 = new SingletonPerson();
const p2 = new SingletonPerson();
console.log(p1 === p2);
但是这种实现方式仍有缺陷,并不能添加原型方法
const SingletonPerson = singleton(Person);
const p1 = new SingletonPerson();
const p2 = new SingletonPerson();
SingletonPerson.prototype.say = function () {
console.log("hello world");
}
p1.say();
下面使用 Proxy
实现,不返回一个新类
,而是代理
,给代理对象的原型上加方法等于直接给该对象的原型加方法。
function singleton(className) {
let ins
return new Proxy(className, {
construct(target, args) {
if (!ins) {
ins = new target(...args);
}
return ins
}
})
}
class Person {
constructor() {
console.log("Person created");
}
}
const SingletonPerson = singleton(Person);
const p1 = new SingletonPerson();
const p2 = new SingletonPerson();
SingletonPerson.prototype.say = function () {
console.log("hello world");
}
p1.say();
console.log(p1 === p2);