Constructores
Cuando los constructores en un contexto OOP están sobrecargados, es mejor utilizar el patrón Factory Pattern para que el código sea limpio.
Mira este pedazo de constructor:
export class Grupo extends Entity {
readonly slug: string
readonly url: string
constructor(
readonly id: number,
readonly title: string,
readonly SEOTitle: string,
readonly description: string,
readonly SEODescription: string,
readonly image: Image,
readonly bgPosition: number,
readonly latitude: number,
readonly longitude: number,
readonly point: MapPoint,
readonly totalPrice: string,
readonly totalTime: number | null,
readonly sabiasque: SabiasQue[] | null,
readonly zona: Zona | null,
readonly startDate: Date | null,
readonly endDate: Date | null,
readonly showWeather: boolean,
readonly gallery: Image[] | null,
readonly pois: Poi[],
readonly grupos: Grupo[],
readonly rutas: Ruta[],
readonly office: Oficina | null,
readonly links: Nullable<{
wikipedia: string
youtube: string
parking: string
parkingAutocaravana: string
googleMaps: string
}> | null,
readonly featured: boolean | null
) {
super()
this.slug = this.createSlug(this.SEOTitle)
this.url = this.getFullUrl(`grupos/${this.id}/${this.slug}`)
}Cuando tratas de instanciar una nueva clase, es un follón porque tienes que introducir los argumentos en orden. Primero id, luego title, luego SEOTitle…
Pero lo peor es que si a futuro se añaden nuevos parámetros, tienes que asegurarse de que el orden sea el correcto en TODOS los lugares en los que se instancia esta clase.
Para ello usamos hacemos el constructor privado y utilizamos un Factory Pattern, un método que encapsula al constructor.
export class Grupo extends Entity {
readonly slug: string
readonly url: string
private constructor(
readonly id: number,
readonly title: string,
readonly SEOTitle: string,
readonly description: string,
readonly SEODescription: string,
readonly image: Image,
readonly bgPosition: number,
readonly latitude: number,
readonly longitude: number,
readonly point: MapPoint,
readonly totalPrice: string,
readonly totalTime: number | null,
readonly sabiasque: SabiasQue[] | null,
readonly zona: Zona | null,
readonly startDate: Date | null,
readonly endDate: Date | null,
readonly showWeather: boolean,
readonly gallery: Image[] | null,
readonly pois: Poi[],
readonly grupos: Grupo[],
readonly rutas: Ruta[],
readonly office: Oficina | null,
readonly links: Nullable<{
wikipedia: string
youtube: string
parking: string
parkingAutocaravana: string
googleMaps: string
}> | null,
readonly featured: boolean | null
) {
super()
this.slug = this.createSlug(this.SEOTitle)
this.url = this.getFullUrl(`grupos/${this.id}/${this.slug}`)
}
static create({
id,
title,
SEOTitle,
description,
SEODescription,
image,
bgPosition,
latitude,
longitude,
point,
totalPrice,
totalTime,
sabiasque,
zona,
startDate,
endDate,
showWeather,
gallery,
pois,
grupos,
rutas,
office,
links,
featured
}: CreateGrupo): Grupo {
return new Grupo(id, title, SEOTitle, description, SEODescription, image, bgPosition, latitude, longitude, point, totalPrice, totalTime, sabiasque, zona, startDate, endDate, showWeather, gallery, pois, grupos, rutas, office, links, featured)
}
export interface CreateGrupo {
id: number
title: string
SEOTitle: string
description: string
SEODescription: string
image: Image
bgPosition: number
latitude: number
longitude: number
point: MapPoint
totalPrice: string
totalTime: number | null
sabiasque: SabiasQue[] | null
zona: Zona | null
startDate: Date | null
endDate: Date | null
showWeather: boolean
gallery: Image[] | null
pois: Poi[]
grupos: Grupo[]
rutas: Ruta[]
office: Oficina | null
links: Nullable<{
wikipedia: string
youtube: string
parking: string
parkingAutocaravana: string
googleMaps: string
}> | null
featured: boolean | null
}De esta manera tenemos encapsulada la creación de la clase Grupo. Si necesitamos modificarla en un futuro, solo tenemos que modificarla aquí sin tener que revisar TODAS las llamadas a new Grupo. Otra ventaja es que al usar un objeto en el que añadimos todos los parámetros, no importa el orden de entrada.
new Grupo(id, SEOTitle, title)Esto daría error, porque el constructor espera que title vaya delante de SEOTitle
Grupo.create({id, SEOTitle, title})Esto funcionaría correctamente porque enviamos todos los argumentos en un objeto y es el Factory Pattern el que se encarga de instanciar la clase con los parámetros recibidos.