使用javascript构建器模式深入了解设计模式

建造者模式 (Builder Pattern)

The builder pattern allows for the creation of a complex object in a procedural manner.

构建器模式允许以过程方式创建复杂对象。

Imagine a scenario where you’re creating an application that allows the user to build their own house. Since you want your users to like your product, you provide them a tremendous amount of options. They can add pools, gardens, internet, walls, and even a roof (imagine that, a real roof!). There are several ways to approach this from a code perspective.

想象一个场景,您正在创建一个应用程序,该应用程序允许用户建造自己的房屋。 由于您希望用户喜欢您的产品,因此可以为他们提供大量选择。 他们可以添加游泳池,花园,互联网,墙壁甚至是屋顶(想象一下,这是一个真正的屋顶!)。 从代码角度来看,有几种方法可以解决此问题。

The first solution is by creating a monster constructor for the House class. This constructor can accept a massive list of parameters that define what properties a given House class has. This has an obvious drawback. As more options are added the constructor grows accordingly; very quickly creating an ugly constructor. Additionally, many times, some parameters will not be used thereby adding unnecessary complexity to the House class.

第一个解决方案是为House类创建一个Monster构造函数。 该构造函数可以接受大量的参数列表,这些参数定义给定House类具有的属性。 这具有明显的缺点。 随着更多选项的添加,构造函数也相应增加。 很快创建了一个丑陋的构造函数。 另外,很多时候,将不会使用某些参数,从而给House类增加了不必要的复杂性。

class House {  
constructor(walls, pool, roof, garden, internet, ...) {...}
}

The second solution is using classical inheritance. You can create a base House class, and create sub-classes for every variation from there. You can probably tell right away that this approach won’t scale at all. The more options you add to the house (like a bathroom perhaps), the more sub-classes you’ll need to add.

第二种解决方案是使用经典继承。 您可以创建一个基本的House类,并为该类中的每个变体创建子类。 您可能会立刻说出这种方法根本无法扩展。 您添加到房屋中的选项越多(也许像浴室),则需要添加的子类就越多。

Builder pattern to the rescue! The builder pattern recommends that you extract the components of the house into a new class. For our use case, let’s call it a HouseBuilder (surprise!). We would then add all the properties as methods on the HouseBuilder. We’d add addPools(), addGardens(), addInternet(), addWalls(), addRoof(), etc. After we add all those methods, we need to add a getHouse() method to retrieve the built house. Something important to note is that you’ll need to reset the builder after you retrieve the product. Conventionally this is done inside the getHouse() method, however you can manually call it from somewhere else.

建造者模式来营救! 构建器模式建议您将房屋的组件提取到新类中。 对于我们的用例,我们称它为HouseBuilder (惊奇!)。 然后,我们将所有属性添加为HouseBuilder上的方法。 我们将添加addPools(), addGardens(), addInternet(), addWalls(), addRoof()等。添加addPools(), addGardens(), addInternet(), addWalls(), addRoof()所有这些方法后,我们需要添加getHouse()方法来检索已建房屋。 需要注意的重要一点是,检索产品后,您将需要重置构建器。 按照惯例,这是在getHouse()方法内部完成的,但是您可以从其他地方手动调用它。

So let’s take a look at a code example with a very basic implementation.

因此,让我们来看一个具有基本实现的代码示例。

class House {
  constructor() {
    this.walls = null;
    this.roof = null;
    this.pool = null;
    this.garden = null;
    this.internet = null;
  }


  setWalls(walls) {
    this.walls = walls;
  }


  setRoof(roof) {
    this.roof = roof;
  }


  setPool(pool) {
    this.pool = pool;
  }


  setGarden(garden) {
    this.garden = garden;
  }


  setInternet(internet) {
    this.internet = internet;
  }
}


class HouseBuilder {
  constructor() {
    this.house = new House();
  }


  buildWalls(walls) {
    this.house.setWalls(walls);
    return this; // returning this for method chaining
  }


  buildRoof(roof) {
    this.house.setRoof(roof);
    return this;
  }


  buildPool(pool) {
    this.house.setPool(pool);
    return this;
  }


  buildGarden(garden) {
    this.house.setGarden(garden);
    return this;
  }


  getHouse() {
    const house = this.house;
    this.reset();
    return house;
  }


  reset() {
    this.house = new House();
  }
}


const house = builder
  .buildWalls(4)
  .buildRoof('sloped')
  .buildGarden(['trees', 'grass', 'peacocks'])
  .getHouse();

And there we have it. A beautiful house.

我们终于得到它了。 漂亮的房子。

Let’s expand on this a bit more though. Say this type of house we just built is a very common house. Let’s call it a FamilyHouse. Everybody loves it. And perhaps there are other very popular combinations. So you decide to create a feature in your product that allows users to choose from a list of predefined house combinations. In order to accomplish this we can add another layer of abstraction by creating what’s known as a director class. The director class defines which build methods we call to build a certain type of house. Let’s take a look at how we would go about creating a director for this type of house.

让我们对此进行更多扩展。 假设我们刚刚建造的这类房屋非常普通。 我们称它为FamilyHouse 。 每个人都喜欢它。 也许还有其他非常流行的组合。 因此,您决定在产品中创建一项功能,该功能允许用户从预定义的房屋组合列表中进行选择。 为了实现这一点,我们可以通过创建所谓的Director类来添加另一层抽象。 Director类定义了我们调用哪种构建方法来构建某种类型的房屋。 让我们看一下如何为这种类型的房屋创建导演。

class Director {
  constructor(builder) {
    this.builder = builder;
  }


  constructFamilyHouse() {
    return this.builder
      .buildWalls(4)
      .buildRoof('sloped')
      .buildGarden(['trees', 'grass', 'peacocks'])
      .getHouse();
  }


  constructMansion() {
    // Steps for building a mansion
  }
}


const director = new Director(new HouseBuilder());
const familyHouse = director.constructFamilyHouse();

And there you have it, a director doing all of the grunt work for you. Now for some pros and cons.

在那里,导演为您完成了所有艰苦的工作。 现在有一些优点和缺点。

Pros:

优点:

  • You control the creation of the object. Step by step by step.

    您可以控制对象的创建。 一步一步一步。
  • Single responsibility principle is adhered to

    坚持单一责任原则

Cons:

缺点:

  • Using this pattern with simple implementations can make the code more complex than strictly necessary.

    将此模式与简单的实现一起使用可使代码变得比严格必要的更为复杂。

That’s all for the builder pattern. In the next article I’ll be discussing the Factory design pattern (not to be confused with the Abstract Factory pattern). See you all there!

这就是构建器模式的全部内容。 在下一篇文章中,我将讨论Factory设计模式(不要与Abstract Factory模式混淆)。 在那里见!

翻译自: https://medium.com/@beckermanyaakov/deep-dive-into-design-patterns-with-javascript-the-builder-pattern-67b4986fc846

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值