TypeScript 实现单例模式

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

单例模式

下面我们学习单例模式,单例模式也是很常用的。它能保证这个类的实例只有一个。

通常在弹窗这种地方会用到单例模式,只允许全局只有唯一一个弹窗。

在这个例子里面,我们想要实现的效果是,当类实例化两次的时候,能够返回同样的实例,也就是下面的代码,打印出 true。

我们先来看看 dialog 弹窗是如何实现的。

首先我们定义了一个私有的静态属性:instance,用来存储这个全局唯一的实例,所以它的类型就是 Dialog。

接着我们定义了一个静态方法:getInstance,用来返回全局唯一的实例,如果它没有被创建的话,就直接 new 一个,如果已经创建的,就直接返回实例即可。

接下来,我们定义了 constructor 构造函数方法,需要注意的是,我们将它定义为 private 私有方法,这样就可以避免直接在外面通过 new 来创建实例,在只允许在这个类的内部通过 new 来创建实例。

class Dialog {
  private static instance: Dialog = null;
  static getInstance() {
    if (!Dialog.instance) {
      Dialog.instance = new Dialog();
    }
    return Dialog.instance;
  }
  /* 
    单例模式,仅允许通过 Dialog.getInstance 获取全局唯一实例
  */
  private constructor() {
    
  }
}

const a = new Dialog();

const b = new Dialog();

console.log(a === b); // 希望这里是 true
复制代码

我们来看下这个报错信息。 image.png

这里的构造函数,是私有方法,所以不可以通过 new 的方式去创建这个实例。

修改下代码

class Dialog {
  private static instance: Dialog = null;
  static getInstance() {
    if (!Dialog.instance) {
      Dialog.instance = new Dialog();
    }
    return Dialog.instance;
  }
  /* 
    单例模式,仅允许通过 Dialog.getInstance 获取全局唯一实例
  */
  private constructor() {

  }
}

const a = Dialog.getInstance();

const b = Dialog.getInstance();

console.log(a === b); // true
复制代码

这样的话,通过这种单例模式,实现这种全局唯一实例的目的。

习题:理解单例模式,并计算生产编号

class Animal {
  private name: string;
  private static id = 0;
  // 工厂模式车间
  constructor(name: string) {
    this.name = name;
    Animal.id++;
  }
  getAnimalInfo() {
    return `我是火星工厂生产的${this.name},生产编号为${Animal.id}`;
  }
  // 单例模式车间(我们车间一生只生成一次,保证全宇宙唯一)
  private static instance: Animal;
  static onlyOne(name: string) {
    if (!Animal.instance) {
      Animal.instance = new Animal(name);
    }
    return Animal.instance;
  }
}

Animal.onlyOne('panda').getAnimalInfo(); // 生产编号为 ?
Animal.onlyOne('panda').getAnimalInfo(); // 生产编号为 ?
复制代码

答案:

1 1

解析:

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

题目使用了单例模式。大家可以仔细看看哦。本题目依然是输出生产编号,生产编号依旧定义为类的静态属性,我们使用了单例模式实现了,类的实例总是唯一存在。因此两次的生产编号均为 1

猜你喜欢

转载自juejin.im/post/7033258031567765517