0基础进大厂,第8天:单例设计模式——面试官:你真的懂唯一的定义

20 阅读4分钟

引言

单例设计模式是应用非常广的一种模式,在许多页面效果中,都能看到单例设计模式的身影。
什么?
你问难吗?
ez

类(Class)

用一份代码带你简单认识JS中的类
现在将这份代码转换为类的写法
构造函数写法

function Point(x, y) {
    this.x = x;
    this.y = y;
}
Point.prototype.toString = function () {
    return `(${this.x},${this.y})`
}
Point.toSum = function (a, b) {
    return a + b;
}
var p = new Point(1, 2);
console.log(p.toString());
console.log(Point.toSum(1, 2));

类的写法
需要注意的点:

  • 写在class里的方法,相当于构造函数里写在.prototype里的公共方法
  • 如果只想类本身访问,用关键字static修饰
  • 关键字static,静态的意思,修饰一个方法就代表着该方法不会被实例化
class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString() {
        return `(${this.x},${this.y})`;
    }
    static toSum(a, b) {
        return a + b;
    }
}
var p = new Point(1, 2);
console.log(p.toString());
console.log(Point.toSum(1, 2));

单例模式

概念:一个类被 new 多次,返回的都是同一个实例对象

面试官:请你手写一份单例模式代码

image.png
接下来让我教你拿捏这个问题
首先,肯定要先创建一个类吧

class SingleMood{
    
}

既然是单例模式,那我问你,我们能直接用关键字new来实现实例化吗?
你是对的!不能
所以,我们该怎么操作?是不是需要在类里面写一个方法,帮助实现实例化,且确保类只实例化一次?
好,我们照着这个思路,更新一下代码。

class SingleMood{
    getInstance(){
        instance = new SingleMood();//暂时不考虑只能被实例化一次的要求,一步一步来
        return instance //返回实例对象
    }
}

我问你,这个新增的方法合适吗?有没有哪里不符合我们的要求?
或者我问你,这个方法实例对象访问合适吗?还是类自己访问才合适?
嗯!你想通了!
当然是类自己访问合适,因为这个方法本身就是用来帮助实现实例化的,所以这个方法只能是类自己访问。
所以,我们要用到关键字static

class SingleMood{
    static getInstance(){
        instance = new SingleMood();//暂时不考虑只能被实例化一次的要求,一步一步来
        return instance  //返回实例对象
    }
}

思考一个核心问题:
如何能判断类自己是否已经被实例化过,并且只实例化一次?
什么?写一个计数器?思路可以,但是我们需要计数吗?或者说,我们是不是只需要判断是否存在就行,对吧
你说什么?写一个标志? 嗯!可以,用标志来判断类是否被实例化,这个思路更进一步了
那我再问你!
谁来当这个标志合适?
啊对!你想明白了!
当然是实例对象自己来当这个标志最合适了!
那实例对象如何才能当这个标志呢?
对了,你说的是对的!
就判断实例对象存不存在就行了!
所以,你肯定想到了,把这个实例对象存进类里面!
你是对的,那我们接着来更新这份代码

class SingleMood{
    static getInstance(){
        SingleMood.instance = new SingleMood();
        return SingleMood.instance  //返回实例对象
    }
}

现在,我们把实例对象存进了类里面。
是不是要接着判断这个实例对象是不是存在类里面?对吧!
如果不存在,我们就实例化SingleMood()
如果存在,我们就返回保存的实例化对象
所以,我们需要接着更新一下代码

class SingleMood {
    static getInstance() {
        if (SingleMood.instance) {
            return SingleMood.instance;
        }
        SingleMood.instance = new SingleMood();
        return SingleMood.instance;
    }
}

这样,我们就完成了手写单例模式,那来验证一下吧
没有一点问题,s1 与 s2完全相等

const s1 = SingleDog.getInstance();
const s2 = SingleDog.getInstance();
console.log(s1 === s2);//true

结束了吗?没有哇!

面试官:请你利用闭包手写一份单例模式代码

思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...
思考一会儿,印象更深刻...

class SingleMood {
}
SingleMood.getInstance = (function () {
    let instance = null;
    return function () {
        if (!instance) {
            return instance = new SingleMood();
        }
        return instance;
    }
})()

总结:

  • 简单认识了类(class),和构造函数没有什么区别,看喜好选择
  • 认识了关键字static
  • 了解了两种实现单例模式的写法

    不足之处,欢迎评论留言指正