????????单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
//创建单例
class SingleTon {
//添加静态私有属性
static #instanse;
//添加静态方法
static getInstanse() {
//判断静态私有属性内是否有实例,如果没有就创建一个并返回,如果有就直接返回
if (this.#instanse === undefined) {
this.#instanse = new SingleTon();
}
return this.#instanse;
}
}
const sing1 = SingleTon.getInstanse();
const sing2 = SingleTon.getInstanse();
console.log(sing1 === sing2); //true
最简单的方式就是希望别人通过 SingleTon.getInstanse()的方式来获得一个实例。但是这种方法不能保证别人不去new一个,这样就不能保证单例了
const sing1 = SingleTon.getInstanse();
const sing2 = new SingleTon();
console.log(sing1 === sing2); //false
ES6新增了模块化,那我直接导出创建的实例,不就能解决问题了吗?我们来看看是否能达到目的。?
//创建单例
class SingleTon {
//添加静态私有属性
static #instanse;
//添加静态方法
static getInstanse() {
//判断静态私有属性内是否有实例,如果没有就创建一个并返回,如果有就直接返回
if (this.#instanse === undefined) {
this.#instanse = new SingleTon();
}
return this.#instanse;
}
}
export default SingleTon.getInstanse();
看起来好像没什么问题,但此处还存在隐患,导出的实例对象可以通过?constructor找到其构造函数,构造函数都找到了,不也可以直接new一个新的实例化对象吗?
<script type="module">
import v from "./SingleTon.js";
const v2 = new v.constructor();
console.log(v2 === v); //false
</script>
通过代理实现单例?
//创建单例
class SingleTon {
//添加静态私有属性
static #instanse;
//添加静态方法
static getInstanse() {
//判断静态私有属性内是否有实例,如果没有就创建一个并返回,如果有就直接返回
if (this.#instanse === undefined) {
this.#instanse = new SingleTon();
}
return this.#instanse;
}
}
//传入一个构造函数,返回一个代理
function SingleTonfn(targetConstructor) {
let ins = null;
const proxy = new Proxy(targetConstructor, {
construct(target, args) {
if (!ins) ins = new targetConstructor(...args);
return ins;
},
});
targetConstructor.prototype.constructor = proxy; //将其原型的指向 指为proxy
return proxy;
}
const v = SingleTonfn(SingleTon);
const v1 = new v();
const v2 = new v();
const v3 = new v1.constructor();
console.log(v1 === v2); //true
console.log(v1 === v3); //true