JavaScript面向对象模式:工厂模式

来自菜鸟教程
跳转至:导航、​搜索

组织代码将使我们免于很多痛苦。 使用面向对象编程的特性,我们可以使用某些设计模式来获得更好的可读性,减少冗余并在需要时创建抽象。 一种这样的模式是工厂模式。

工厂模式是一种遵循 DRY 方法的面向对象模式。 顾名思义,对象实例是通过使用工厂为我们制作所需的对象来创建的。

让我们看一个使用工厂模式组装 alligator 对象的非常简单的示例。 为此,我们首先需要创建为我们创建 alligator 零件的工厂:

class TailFactory {
  constructor(props) {
    this.tailLength = props.tailLength;
  }
};

class TorsoFactory {
  constructor(props) {
    this.color = props.color;
  }
};

class HeadFactory {
  constructor(props) {
    this.snoutLenth = props.snoutLenth;
  }
};

现在,我们创建一个类作为实际工厂类和用户之间的中介。 我们称之为 ReptilePartFactory

class ReptilePartFactory {
  constructor(type, props) {
    if(type === "tail")
      return new TailFactory(props);
    if(type === "torso")
      return new TorsoFactory(props);
    if(type === "head")
      return new HeadFactory(props);
  }
};

现在让我们继续组装真正的鳄鱼,并使用 ReptilePartFactory 为我们获取所需的零件:

let alligator = {};
let alligatorProps = {
  tailLength : 2.5, 
  color: "green",
  snoutLenth: 1
};

//gets a tail from the tail factory
alligator.tail  = new ReptilePartFactory("tail", alligatorProps); 

//gets a torso from the torso factory
alligator.torso = new ReptilePartFactory("torso", alligatorProps);

//gets a head from the head factory
alligator.head  = new ReptilePartFactory("head", alligatorProps);

看看上面的模式,似乎我们可以使用相同的 ReptilePartFactory 来为类似鳄鱼的对象创建部件。 背景中的工厂永远不必知道最终对象的性质。

因此,使用工厂模式给了我们一些优势:

  • 动态对象创建:可用于在运行时确定对象类型的情况。
  • Abstraction:用户永远不必访问实际对象的构造函数。
  • 可重用性/维护:相同的工厂可以用于类似的对象,它允许我们轻松添加/删除新的对象类,而无需更改大量代码。

现在我们对工厂模式有了一些了解,让我们来探索一下如何编写更好的工厂模式代码。

上面的示例使用 if-ladder 根据用户输入找出要调用的工厂。 这是一个简单的实现,直观且对更改不太开放。 如果我们以后有新的零件要添加,那么我们就不得不打扰ReptilePartFactory。 这违反了 SOLID 原则,即“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”。

我们如何将工厂类存储在一个对象中,并使用我们想要的部分作为键调用所需的部分工厂? 首先我们必须注册工厂,它很简单:

let registeredPartFactories = {};
registeredPartFactories['tail'] = class TailFactory{
  ...
};

registeredPartFactories['torso'] = class TorsoFactory {
  ...
};

registeredPartFactories['head'] = class HeadFactory {
  ...
};

现在,抽象层可以像这样调用工厂:

class ReptilePartFactory {
  constructor(type, props) {
    return new registeredPartFactories[type](props);
  }
};

这种方法更简洁,允许扩展我们的工厂而不影响 ReptilePartFactory 中的代码。

综上所述

还有其他几种面向对象的模式也提高了可读性和质量。 因此,在使用工厂模式之前,请检查是否有真正的需求。 如果您要重复创建类似类型的对象,并且还需要一个层来使用这些对象创建新实例,同时为创建逻辑提供一定程度的抽象,那么可以——工厂模式是一个不错的选择。