Super tediosa la implementación en JS
Introduccion
Dónde estamos y hacia dónde vamos
Patrones creacionales
Singleton
Singleton 101
Implementación de Singleton en JS
Contrastemos: Singleton con TS
Singleton: pros y contras
Factory
Factory 101
Diagrama de implementación de Factory
Implementación de Factory en JS
Contrastemos: Factory en TS
Factory: pros y contras
Abstract Factory
Abstract Factory 101
Diagrama de implementación de Abstract Factory
Implementación de Abstract Factory en JS
Contrastemos: Abstract Factory en TS
Abstract Factory: pros y contras
Builder
Builder 101
Diagrama de implementación de Builder
Implementación de Builder en JS
Contrastemos: Builder en TS
Builder: pros y contras
Prototype
Prototype 101
Diagrama de implementación de Prototype
Implementación de Prototype en JS
Contrastemos: Prototype en TS
Prototype: pros y contras
Conclusiones
¿Qué sigue sobre patrones de diseño?
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Daniel Basulto
Aportes 14
Preguntas 1
Super tediosa la implementación en JS
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());
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!
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)
Se me ocurren dos formas de variar la implementación de la clase Director:
Director.setProductionLine(mastodonSedanProductionLine).constructCvtEdition()
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?