TypeScript 中实现工厂模式

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

工厂模式

下面我们学习一些面向对象编程中,一些常用的设计模式,如何在 TS 中实现?

一个设计模式,是能够解决一个问题。我们学设计模式,最重要的是,知道这种设计模式发源于哪;为什么要这么设计;它能够解决什么问题?

那我们先来学习一个最简单的设计模式:工厂模式。

先来看下这个例子:

// 橘子罐头
class CannedOrange {}
​
// 苹果罐头
class CannedApple {}
​
// 吃一个罐头
function eatCan(c: CannedApple | CannedOrange) {
​
}
​
let o = new CannedOrange();
eatCan(o);
复制代码

我们有几个罐头:橘子罐头、苹果罐头,然后还有一个吃一个罐头的方法,它的输入是其中某一种罐头,接下来,我们创建了一个橘子罐头,然后把它吃了。

从上面这个例子,大家可以看出有什么可以改进的地方吗?

类型定义,比较麻烦,使用到了联合类型,以后每增加一种罐头,都需要再添加一个类型,代码耦合比较高,有没有什么优化方法呢?

我们可以定义一个抽象罐头,所有的罐头都得继承这个抽象罐头。

// 抽象罐头
abstract class Can {}
​
// 橘子罐头
class CannedOrange extends Can {}
​
// 苹果罐头
class CannedApple extends Can {}
​
// 吃一个罐头
function eatCan(c: Can) {
​
}
​
let o = new CannedOrange();
eatCan(o);
​
复制代码

那下面还有什么优化的地方呢?

我们注意到这里我们定义了一个橘子罐头,是直接使用 new 创建出来的,这里的话,就需要我们知道创建的罐头的类的名字是什么,假如这个文件比较大,或者类分布在其他地方,我们在new 的时候,就不知道有哪些罐头可以被创建。

扫描二维码关注公众号,回复: 13294540 查看本文章

这个时候,就可以使用工厂模式,将罐头的创建,放到这个工厂里面,我们来看下这个工厂类,这样的话,就可以实现简单的罐头工厂。

// 抽象罐头
abstract class Can {}
​
// 橘子罐头
class CannedOrange extends Can {}
​
// 苹果罐头
class CannedApple extends Can {}
​
type CanTypes = 'orange' | 'apple';
​
class CanFactory {
  static createCan(CanType: CanTypes) {
    if (CanType === 'apple') {
      return new CannedApple();
    } else if(CanType === 'orange') {
      return new CannedOrange();
    }
  }
}
​
​
// 吃一个罐头
function eatCan(c: Can) {
​
}
​
let p = CanFactory.createCan('apple');
eatCan(p);
​
复制代码

下面我们来试一下创建一个罐头,在调用的时候,只要打一个引号,就会提示有哪几种罐头可以创建。这样就解决了之前无法预知罐头名称的问题了。

习题:理解工厂模式,并计算生产编号

class Animal {
  private name: string;
  private static id = 0;
  // 工厂模式车间
  constructor(name: string) {
    this.name = name;
    Animal.id++;
  }
  getAnimalInfo() {
    return `我是火星工厂生产的 ${this.name},生产编号为 ${Animal.id}`;
  }
}
​
​
new Animal('panda').getAnimalInfo(); // 生产编号为 ?
new Animal('panda').getAnimalInfo(); // 生产编号为 ?
复制代码

答案:1 2

解析:

工厂模式常用的实例化对象模式,用于批量生产对象。

题目使用了工厂模式。大家可以仔细看看哦。解决本题的思路是类的静态属性,所有的实例共享类的静态属性。所有编号分别为 12

猜你喜欢

转载自juejin.im/post/7032983652581507102