You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesi贸n a prueba de IA

Antes: $249

Currency
$209
Suscr铆bete

Termina en:

0 D铆as
6 Hrs
38 Min
45 Seg

Implementaci贸n de Builder en JS

19/27
Resources

What is the Builder pattern and how does it apply to car production?

The Builder pattern is one of the most effective techniques for handling complex constructions in programming. In this context, we implemented the Builder pattern in the car production line. Its main goal is to simplify the process of creating complex objects by separating the creation process into small and manageable steps. Here you will find the details of how this pattern is implemented in car production, specifically using JavaScript.

How is the base class or Builder interface defined?

The first step in implementing the Builder pattern is to define a base class or interface that stipulates the general steps for building specific products. For the car production context, we define the CarProductionLine class with essential methods such as airbag configuration, color, and car editing. Here is a code example:

class CarProductionLine { setAirbags(howMany) { throw new Error('Method not implemented'); } setColor(color) { throw new Error('Method not implemented'); } setEdition(edition) { throw new Error('Method not implemented'); } resetProductionLine() { throw new Error('Method not implemented'); } }}

Each method in our base class throws an error if it is not implemented, ensuring that all builder classes must define these methods.

How do we implement concrete builders?

The second step is to implement concrete builders to provide different implementations of the steps defined in the base class. For example, in the sedan factory we create the SedanProductionLine class that provides concrete implementations for the production process:

class SedanProductionLine extends CarProductionLine { setAirbags(howMany) { this.sedanCar.airbags = howMany; return this; }
 setColor(color) { this.sedanCar.color = color; return this; }
 setEdition(edition) { this.sedanCar.edition = edition; return this; }
 resetProductionLine() { const model = this.internalModel; this.sedanCar = model === 'Mastodon' ? new Mastodon() : new Rhino(); } }}

Thanks to the use of this, we can chain methods in an elegant and efficient way, facilitating the customization of the vehicle.

What is the purpose of the director class and how is it used?

The director class is responsible for knowing and defining the exact process to build the variations of the product. Thus, it establishes an order in the construction steps. Here is how we set up a director to manage the build of different car editions:

class Director { setBuilder(builder) { this.productionLine = builder; } }
 constructCVTEdition() { this.productionLine.setAirbags(4).setColor('Blue').setEdition('CVT'); } }
 constructSignatureEdition() { this.productionLine.setAirbags(8).setColor('Red').setEdition('Signature'); } }}

The director ensures that the steps are followed in a particular order and allows reuse of the same builder for different product configurations.

How is the creation of final products handled?

Driven by the director, the builder is able to assemble the product and deliver it already configured, maintaining the state of the process and ensuring that the product is ready to be used:

const director = new Director();const mastodonProductionLine = new SedanProductionLine('Mastodon');director.setBuilder(mastodonProductionLine);director.constructCVTEdition();
const mastodonCar = mastodonProductionLine.build();console.log(mastodonCar);

The build method returns the car resulting from the assigned configuration, showing how the various build methods affect the final product.

What does the Builder pattern bring to software development?

Implementing the Builder pattern not only organizes the code but also allows flexible handling of the creation of complex objects, reducing the risk of errors and providing more maintainable code. By separating build actions into several classes, including builders and the manager, responsibilities are clearly defined and decoupled. In addition, this structure is especially valuable when products are expected to enter and exit the production process in different ways based on certain parameters.

Now it's your turn to apply the Builder pattern and see how it fits your development needs! Remember, practice is key to mastering any programming methodology - go ahead and keep building!

Contributions 16

Questions 1

Sort by:

Want to see more contributions, questions and answers from the community?

Super tediosa la implementaci贸n en JS

No termino de entender por qu茅 al curso no le pusieron directamente "**Patrones de Dise帽o Creacionales en TypeScript**"... con toda la sinceridad del mundo, dejando aparte lo incre铆blemente retorcidos y poco aplicables que son los ejemplos y el tema autos (que me parece de plano una elecci贸n poco acertada y compleja al punto de haber tenido que googlear cada t茅rmino para entender de qu茅 est谩bamos hablando), las implementaciones en JavaScript van en contra de todo lo que uno quiere para su c贸digo: infinidad de l铆neas, cantidad de clases y c贸digo completamente gen茅rico que no cumple ning煤n papel, y un largo etc. **POV:** Muy poca motivaci贸n para continuar cursando... pero est谩 como obligatorio para la rama de JavaScript... asique a seguir sufriendo cada vez un poco m谩s con cada clase... ya ni ganas tengo de abrir el editor de c贸digo.

Lo veo muy util para abstraer la complejidad de la construcci贸n de objetos cuyo constructor requiere varios par谩metros y no siempre son obligatorios. Una clase Builder, abstrae esta complejidad y facilita el uso del objeto. En este ejemplo m谩s de la vida real he imaginado como pagar la liquidaci贸n de un empleado, en este caso hay varios factores que intervienen en el c谩lculo. Aqu铆 es donde entra el patr贸n:

class Liquidation {
    private basicSalaryMontly: number;
    private monthsWorked: number;
    private pendingHolyDays: number;
    private premiumEndYear: number;
    private premiumMediumYear: number;
    private layoffs: number;

    /**
     *
     */
    constructor(
        basicSalaryMontly: number,
        monthsWorked: number,
        pendingHolyDays: number,
        premiumEndYear: number,
        premiumMediumYear: number,
        layoffs: number) {

        this.basicSalaryMontly = basicSalaryMontly;
        this.monthsWorked = monthsWorked;
        this.pendingHolyDays = pendingHolyDays;
        this.premiumEndYear = premiumEndYear;
        this.premiumMediumYear = premiumMediumYear;
        this.layoffs = layoffs;
    }

    Calculate() {
        const totalPendingHollyDays = ((this.basicSalaryMontly / 30) * 365) * this.pendingHolyDays;
        const total = (this.basicSalaryMontly * this.monthsWorked) + totalPendingHollyDays + this.premiumEndYear + this.premiumMediumYear + this.layoffs;
        console.log("Vacaciones pendientes: ", totalPendingHollyDays);
        console.log("Liquidaci贸n Total ", total);
    }
}

class LiquidationBuilder {
    private basicSalaryMontly: number;
    private monthsWorked: number;
    private pendingHolyDays: number;
    private premiumEndYear: number;
    private premiumMediumYear: number;
    private layoffs: number;


    setBasicSalaryMonth(basicSalaryMontly: number): LiquidationBuilder {
        this.basicSalaryMontly = basicSalaryMontly;
        return this;
    }

    setMothsWorked(monthsWorked: number): LiquidationBuilder {
        this.monthsWorked = monthsWorked;
        return this;
    }

    setPendingHollyDays(pendingHolyDays: number): LiquidationBuilder {
        this.pendingHolyDays = pendingHolyDays;
        return this;
    }

    setPremiumEndYear(premiumEndYear: number): LiquidationBuilder {
        this.premiumEndYear = premiumEndYear;
        return this;
    }

    setPremiumMediumYear(premiumMediumYear: number): LiquidationBuilder {
        this.premiumMediumYear = premiumMediumYear;
        return this;
    }

    setLayoffs(layoffs: number): LiquidationBuilder {
        this.layoffs = layoffs;
        return this;
    }

    build(): Liquidation {
        return new Liquidation(this.basicSalaryMontly, this.monthsWorked, this.pendingHolyDays,
            this.premiumEndYear, this.premiumMediumYear, this.layoffs);
    }
}

const total = new LiquidationBuilder()
    .setBasicSalaryMonth(4500)
    .setLayoffs(500)
    .setMothsWorked(15)
    .setPremiumEndYear(1000)
    .setPremiumMediumYear(0)
    .setPendingHollyDays(15)
    .build();

console.log(total);
console.log(total.Calculate());

隆Hola!

Considero que ser铆a bueno para el curso darnos un ejemplo de aplicar este patr贸n de dise帽o no tan complejo, algo m谩s corto y ah铆 si complementar con el ejemplo de los carros que se lleva trabajando en los anteriores patrones de dise帽o y ahondar un poco m谩s en los requerimientos, con m谩s diagramas y un puntero explicando la historia de usuario, considero que en esta clase se agreg贸 un nivel de complejidad para aplicar el patr贸n a este ejemplo que quiz谩s se puede ver un poco forzado, ser铆a tener una introducci贸n al patr贸n Builder m谩s corta y ah铆 pasar a este ejemplo, algo m谩s sencillo podr铆a ser el proceso de creaci贸n de una pizza con Builder como el siguiente:

// Clase Pizza
class Pizza {
  private dough: string;
  private sauce: string;
  private cheese: string;
  private toppings: string[];

  constructor(
    dough: string,
    sauce: string,
    cheese: string,
    toppings: string[]
  ) {
    this.dough = dough;
    this.sauce = sauce;
    this.cheese = cheese;
    this.toppings = toppings;
  }

  public getDough(): string {
    return this.dough;
  }

  public getSauce(): string {
    return this.sauce;
  }

  public getCheese(): string {
    return this.cheese;
  }

  public getToppings(): string[] {
    return this.toppings;
  }
}

// Builder
class PizzaBuilder {
  private dough: string;
  private sauce: string;
  private cheese: string;
  private toppings: string[];

  constructor() {
    this.toppings = [];
  }

  public setDough(dough: string): PizzaBuilder {
    this.dough = dough;
    return this;
  }

  public setSauce(sauce: string): PizzaBuilder {
    this.sauce = sauce;
    return this;
  }

  public setCheese(cheese: string): PizzaBuilder {
    this.cheese = cheese;
    return this;
  }

  public addTopping(topping: string): PizzaBuilder {
    this.toppings.push(topping);
    return this;
  }

  public build(): Pizza {
    return new Pizza(this.dough, this.sauce, this.cheese, this.toppings);
  }
}

// Uso
const pizza = new PizzaBuilder()
  .setDough('thin')
  .setSauce('tomato')
  .setCheese('mozzarella')
  .addTopping('mushrooms')
  .addTopping('olives')
  .addTopping('onions')
  .build();

console.log(pizza.getDough()); // thin
console.log(pizza.getSauce()); // tomato
console.log(pizza.getCheese()); // mozzarella
console.log(pizza.getToppings()); // ['mushrooms', 'olives', 'onions']

En el anterior ejemplo, no se dej贸 una clase Director ya que seg煤n refactoring.guru una clase Director no es estrictamente necesaria (aunque recomendada), tambi茅n recomiendo 茅charle un vistazo al link para mayor entendimiento de este patr贸n de dise帽o.

隆Gracias por la clase!

Recomiendo el uso de ejemplos m谩s cortos, m谩s sencillos, m谩s explicables. O tambi茅n podr铆amos tener otro curso que sea exclusivamente pr谩ctico por ejemplo que tenga 20 proyectos. 5 proyectos por cada tipo de patr贸n de dise帽o creacional en Javascript. Pienso que de esa forma podr铆amos estar m谩s conformes.
<https://www.youtube.com/watch?v=5et6PxMDVXo&ab_channel=MarluanEspiritusanto> Un ejemplo馃憜 un poco diferente que me ayudo a entender.

Otro ejemplo diferente en python

class Car:
    def __init__(self):
        self.brand = None
        self.model = None
        self.color = None
        self.engine = None
        self.transmission = None

    def __str__(self):
        return f"Coche: {self.brand} {self.model}, Color: {self.color}, Motor: {self.engine}, Transmisi贸n: {self.transmission}"

class CarBuilder:
    def __init__(self):
        self.car = Car()

    def set_brand(self, brand):
        self.car.brand = brand
        return self

    def set_model(self, model):
        self.car.model = model
        return self

    def set_color(self, color):
        self.car.color = color
        return self

    def set_engine(self, engine):
        self.car.engine = engine
        return self

    def set_transmission(self, transmission):
        self.car.transmission = transmission
        return self

    def build(self):
        return self.car

class CarDirector:
    def __init__(self, builder):
        self.builder = builder

    def construct_sports_car(self):
        return self.builder.set_brand("Ferrari") \
                          .set_model("488 GTB") \
                          .set_color("Rojo") \
                          .set_engine("V8") \
                          .set_transmission("Autom谩tica") \
                          .build()

    def construct_suv(self):
        return self.builder.set_brand("BMW") \
                          .set_model("X5") \
                          .set_color("Negro") \
                          .set_engine("V6") \
                          .set_transmission("Autom谩tica") \
                          .build()

# Uso del Builder y el Director para construir diferentes tipos de coches
builder = CarBuilder()
director = CarDirector(builder)

sports_car = director.construct_sports_car()
suv = director.construct_suv()

print(sports_car)
print(suv)
Complicada
No entiendo la necesidad de ser cr铆ptico en la explicaci贸n. Estoy intentando hacer un paso a paso en mis notas de la clase y alrededor del minuto 10 el instructor empieza a colocar variables que se supone debo adivinar. Si me pareci贸 errado colocar la palabra reservada super sin estar heredando nada de la clase base, pero como se supone que voy a adivinarlo si quien tiene el c贸digo en la cabeza es el? No me gusta este profesor la verdad. Siento que se enreda solo en su explicaci贸n.
he visto lo primera parte del video unas 3 veces y no entiendo el porque de la funcion resetbuilder隆 alguien me lo puede explicar porfa.
este codigo me esta volando la cabeza, creo que necesitare tiempo extra para entenderlo e interiorisarlo
Interesante saber que se pudo implementar este patr贸n en JS. Sin embargo, fue demasiado tedioso, demasiadas clases... JS esta muy enfocado en programaci贸n funcional ? O Es lo que siempre he visto, ha sido tedioso pero divertido ver estas implementaciones en JS.
Tengo unas dudas...聽 Primero: por qu茅 crear 2 m茅todos "construct" espec铆ficos, en vez de 1 que reciba par谩metros como la cantidad de airbags, color y edici贸n? Algo as铆 dentro de la clase Director: ```txt construct(airbags, color, edition) { this.productionLine .setAirBags(airbags) .setColor(color) .setEdition(edition); } ``` Segundo: por qu茅 si el Director es quien "construye" el carro, no es el mismo Director el que "arme" (build). De esa manera no es necesario manejar la instancia de la l铆nea de producci贸n que se est茅 trabajando, sino que el Director se encarga de eso. Nuevamente dentro de la clase Director: ```js build(){ return this.productionLine.build() } ```Entonces en el appBuilder, se puede llamar de esta manera: ```js const mastodonSedanProductionLine = new SedanProductionLine({ modelToCustomizeInLine: 'mastodon', }); director.construct(airbags=4, color='blue', edition='CVT'); const mastodnSedanCvt = director.build(); console.log('--- Mastodon Sedan CVT ---\n', mastodnSedanCvt); ```En la explicaci贸n, hay un peque帽o error creo: ```js * 2. Implement concrete builders subclasses that offer different * versions of the build steps. These builders could create * concrete products or base ones. Depends on what we need. * * SedanProductionLine: build() -> {Mastodon|Rhino}Car | Car * RhinoProductionLine: build() -> {Mastodon|Rhino}Car | Car ```Dice RhinoProductionLine, cuando entiendo deber铆a ser HatchbackProductionLine, porque hace referencia al Tipo de veh铆culo y no al modelo.
馃煝 La verdad con el ejemplo de los carros tomo mas complejidad, despu茅s de revisar paso por paso las l铆neas de c贸digo y con el diagrama, pude entender la explicaci贸n de las clases anteriores, <u>la divisi贸n de pasos para la creaci贸n de un objeto</u> y **adem谩s con la anidaci贸n de funciones**.
ufff patron builder agregado mentalmente al terminar el ejercicio completo y revisarlo una hora jajaja, pero qued贸 entendido.... la idea basica es devolver un objeto que esta construido por peque帽as partes de una clase llamada "Builder". Si estoy mal me corrijen... sino a seguir aprendiendo !

Se me ocurren dos formas de variar la implementaci贸n de la clase Director:

  1. Un director por cada l铆nea de producci贸n
    No s茅 si estoy equivocado, pero se me ocurre que es buena idea tener varios directores, cada uno encargado de una l铆nea de producci贸n y que la reciba por el m茅todo constructor al instanciarse.
  2. Director basado en m茅todos est谩ticos
    El ejemplo del profesor podr铆a funcionar perfecto sin tener que instanciar un director. Si asumimos que todos los m茅todos mostrados en clase fueras est谩ticos, podr铆amos hacer esto:
    Director.setProductionLine(mastodonSedanProductionLine).constructCvtEdition()