← 返回首页
Javascript基于代理实现单例模式
发表时间:2023-01-12 17:02:00
Javascript基于代理实现单例模式

Javascript如何实现单例模式呢?

1.非单例模式

我们先看以下的非单例模式。

module/video.js


class Video {
    name = '';
    constructor(name) {
        this.name = name;
        console.log(this.name + ',is constructed....')
    }
}

Video.prototype.play = function(){
    console.log(this.name+" is playing...")
}

test.js

import {Video} from './module/video.js'

const v1 = new Video('钢琴');
const v2 = new Video('小提琴');

console.log(v1===v2);

v1.play();
v2.play();

运行结果:


钢琴,is constructed....
小提琴,is constructed....
false
钢琴 is playing...
小提琴 is playing...

v1和v2显然是两个不同的对象,是非单例的。

2.传统方式实现单例。

module/singleton.js

export function singleton(className){
    let ins;
    return class {
        constructor(...args) {
            if(!ins){
                ins = new className(...args);
            }
            return ins;
        }
    }    
}

module/video.js

import {singleton} from "./singleton.js";

class Video {

    name = '';
    constructor(name) {
        this.name = name;
        console.log(this.name + ',is constructed....')
    }
}


Video.prototype.play = function(){
    console.log(this.name+" is playing...")
}

const videoInstance = singleton(Video);

export {videoInstance as Video};

test.js

import {Video} from './module/video.js'

const v1 = new Video('钢琴');
const v2 = new Video('小提琴');

console.log(v1===v2);

v1.play();
v2.play();

运行结果:


钢琴,is constructed....
true
钢琴 is playing...
钢琴 is playing...

这个结果看起来似乎一切正常。但是如果我们在创建完对象之后,无法在原型链上定义新方法,例如:

test.js

import {Video} from './module/video.js'

const v1 = new Video('钢琴');
const v2 = new Video('小提琴');

console.log(v1===v2);

v1.play();
v2.play();

Video.prototype.stop=function(){
    console.log(this.name+" is stop playing....");
}

v1.stop();
v2.stop();   

运行结果:

钢琴,is constructed....                                            
true                                                               
钢琴 is playing...                                                 
钢琴 is playing...                                                 
file:///E:/node_project/test.js:19                                 
v1.stop();                                                         
   ^                                                               

TypeError: v1.stop is not a function    

3.使用代理实现单例

module/singleton.js

export function singleton(className){
    let ins;

    return new Proxy(className,{
        construct(target, argArray, newTarget) {
            if(!ins){
                ins = new target(...argArray);
            }
            return ins;
        }
    })
}

module/video.js

import {singleton} from "./singleton.js";

class Video {

    name = '';
    constructor(name) {
        this.name = name;
        console.log(this.name + ',is constructed....')
    }
}

Video.prototype.play = function(){
    console.log(this.name+" is playing...")
}

const videoInstance = singleton(Video);

export {videoInstance as Video};

test.js

import {Video} from './module/video.js'

const v1 = new Video('钢琴');
const v2 = new Video('小提琴');

console.log(v1===v2);

v1.play();
v2.play();

Video.prototype.stop=function(){
    console.log(this.name+" is stop playing....");
}

v1.stop();
v2.stop();

运行结果:

钢琴,is constructed....
true                     
钢琴 is playing...       
钢琴 is playing...       
钢琴 is stop playing.... 
钢琴 is stop playing....