No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Abstract Factory: pros y contras

16/27
Recursos

Aportes 19

Preguntas 4

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

Les dejo mi codigo en TypeScript por si les es de ayuda:

// declaramos interfaces por cada producto base
interface Cpu {
  setSeries(series: string): void;
}

interface Memory {
  setCapacityInGb(gb: number): void;
}

interface Display {
  setResolution(): void;
}

// declaramos class por cada producto en concreto
class PhoneCpu implements Cpu {
  setSeries(series: string): void {
    console.log(`Phone ${series}`);
  }
}

class LaptopCpu implements Cpu {
  setSeries(series: string): void {
    console.log(`Laptop ${series}`);
  }
}

class TabletCpu implements Cpu {
  setSeries(series: string): void {
    console.log(`Tablet ${series}`);
  }
}

class PhoneMemory implements Memory {
  setCapacityInGb(gb: number): void {
    console.log(`Phone ${gb}gb`);
  }
}

class LaptopMemory implements Memory {
  setCapacityInGb(gb: number): void {
    console.log(`Laptop ${gb}gb`);
  }
}

class TabletMemory implements Memory {
  setCapacityInGb(gb: number): void {
    console.log(`Tablet ${gb}gb`);
  }
}

class PhoneDisplay implements Display {
  setResolution(): void {
    console.log("Phone resolution...");
  }
}

class LaptopDisplay implements Display {
  setResolution(): void {
    console.log("Laptop resolution...");
  }
}

class TabletDisplay implements Display {
  setResolution(): void {
    console.log("Tablet resolution...");
  }
}

// declaramos interface para abstract factory
interface AFactory {
  createCpu(): Cpu;
  createMemory(): Memory;
  createDisplay(): Display;
}

// declaramos class para fabricas concretas de productos
class PhoneFactory implements AFactory {
  createCpu(): Cpu {
    return new PhoneCpu();
  }
  createMemory(): Memory {
    return new PhoneMemory();
  }
  createDisplay(): Display {
    return new PhoneDisplay();
  }
}

class LaptopFactory implements AFactory {
  createCpu(): Cpu {
    return new LaptopCpu();
  }
  createMemory(): Memory {
    return new LaptopMemory();
  }
  createDisplay(): Display {
    return new LaptopDisplay();
  }
}

class TabletFactory implements AFactory {
  createCpu(): Cpu {
    return new TabletCpu();
  }
  createMemory(): Memory {
    return new TabletMemory();
  }
  createDisplay(): Display {
    return new TabletDisplay();
  }
}

// funciones de implementacion
const appFactoryNew = (factory: AFactory) => {
  const cpu = factory.createCpu();
  const memory = factory.createMemory();
  const display = factory.createDisplay();

  cpu.setSeries("i5");
  memory.setCapacityInGb(512);
  display.setResolution();
};

type FactoryTypeNew = "phone" | "laptop" | "tablet";

const createFactoryNew = (type: FactoryTypeNew) => {
  const factories = { phone: PhoneFactory, laptop: LaptopFactory, tablet: TabletFactory };
  const Factory = factories[type];
  return new Factory();
};

appFactoryNew(createFactoryNew("phone"));
appFactoryNew(createFactoryNew("laptop"));
appFactoryNew(createFactoryNew("tablet"));

Les comparto mi codigo

// Paso 1
interface CPU {
    setSeries(serie: string): void
}

interface Memory {
    setCapacityInGB(capacity: number): void
}

interface Display {
    setResolution(resolution: '1920' | '720' | '480'): void
}

// Paso 2
// CPU
// Phone
class CPUPhone implements CPU {
    serie: string

    public setSeries(serie: string): void {
        this.serie = serie
    }
}

// Laptop
class CPULaptop implements CPU {
    serie: string

    public setSeries(serie: string): void {
        this.serie = serie
    }
}

// Tablet
class CPUTablet implements CPU {
    serie: string

    public setSeries(serie: string): void {
        this.serie = serie
    }
}

// Memory
// Phone
class MemoryPhone implements Memory {
    capacityInGB: number

    public setCapacityInGB(capacity: number): void {
        this.capacityInGB = capacity
    }
}

// Laptop
class MemoryLaptop implements Memory {
    capacityInGB: number

    public setCapacityInGB(capacity: number): void {
        this.capacityInGB = capacity
    }
}

// Tablet
class MemoryTablet implements Memory {
    capacityInGB: number

    public setCapacityInGB(capacity: number): void {
        this.capacityInGB = capacity
    }
}

// Display
// Phone
class DisplayPhone implements Display {
    resolution: string

    public setResolution(resolution: "1920" | "720" | "480"): void {
        this.resolution = resolution
    }
}

// Laptop
class DisplayLaptop implements Display {
    resolution: string

    public setResolution(resolution: "1920" | "720" | "480"): void {
        this.resolution = resolution
    }
}

// Tablet
class DisplayTablet implements Display {
    resolution: string

    public setResolution(resolution: "1920" | "720" | "480"): void {
        this.resolution = resolution
    }
}

// Paso 3
interface ComponentAbstractFactory {
    createCPU(): CPU
    createMemory(): Memory
    createDisplay(): Display
}

// Paso 4
// Phone
class PhoneFactory implements ComponentAbstractFactory {
    public createCPU(): CPU {
        return new CPUPhone()
    }

    public createDisplay(): Display {
        return new DisplayPhone()
    }

    public createMemory(): Memory {
        return new MemoryPhone()
    }
}

// Laptop
class LaptopFactory implements ComponentAbstractFactory {
    public createCPU(): CPU {
        return new CPULaptop()
    }

    public createDisplay(): Display {
        return new DisplayLaptop()
    }

    public createMemory(): Memory {
        return new MemoryLaptop()
    }
}

// Tablet
class TabletFactory implements ComponentAbstractFactory {
    public createCPU(): CPU {
        return new CPUTablet()
    }

    public createDisplay(): Display {
        return new DisplayTablet()
    }

    public createMemory(): Memory {
        return new MemoryTablet()
    }
}

function appAbstractFactory(factory: ComponentAbstractFactory): void {
    const cpu = factory.createCPU()
    const memory = factory.createMemory()
    const display = factory.createDisplay()
}

function createFactory(type: 'phone' | 'laptop' | 'tablet'): ComponentAbstractFactory {
    const factories = {
        phone: PhoneFactory,
        laptop: LaptopFactory,
        tablet: TabletFactory
    }

    const Factory = new factories[type]
    return Factory
}

appAbstractFactory(createFactory('phone'))
appAbstractFactory(createFactory('laptop'))
appAbstractFactory(createFactory('tablet'))


// BASE PRODUCTS
interface CPUBase {
    setSeries(_series: string): void
}

interface MemoryBase {
    setCapacityInGB(_gbs: number): void
}

interface DisplayBase {
    setResolution(): void
}


// CONCRETE PRODUCTS
class CPU implements CPUBase {
    setSeries(_series: string): void {
        console.log(`CPU: ${_series}`)
    }
}

class Memory implements MemoryBase {
    setCapacityInGB(_gbs: number): void {
        console.log(`Memory: ${_gbs} Gigabytes`)
    }
}

class Display implements DisplayBase {
    setResolution(): void {
        console.log(`FHD`)
    }
}

// CREATION FOR EACH BASE PRODUCT
interface ProductsAbstractFactory {
    createCPU(): CPUBase
    createMemory(): MemoryBase
    createDisplay(): DisplayBase
}


// CONCRETE FACTORIES
class PhoneDeviceFactory implements ProductsAbstractFactory {
    createCPU(): CPUBase {
        return new CPU()
    }

    createMemory(): MemoryBase {
        return new Memory()
    }

    createDisplay(): DisplayBase {
        return new Display()
    }

}

class LaptopDeviceFactory implements ProductsAbstractFactory {
    createCPU(): CPUBase {
        return new CPU()
    }

    createMemory(): MemoryBase {
        return new Memory()
    }

    createDisplay(): DisplayBase {
        return new Display()
    }

}

class TabletDeviceFactory implements ProductsAbstractFactory {
    createCPU(): CPUBase {
        return new CPU()
    }

    createMemory(): MemoryBase {
        return new Memory()
    }

    createDisplay(): DisplayBase {
        return new Display()
    }

}

// APP EJECUTION
const appDevicesFactory = (factory: ProductsAbstractFactory) => {

    const cpu = factory.createCPU()
    const memory = factory.createMemory()
    const display = factory.createDisplay()

    cpu.setSeries('[CPU]')
    memory.setCapacityInGB(1000)
    display.setResolution()
}


type FactoryType = 'phone' | 'laptop' | 'tablet'
type FactoriesTypes = {
    phone: typeof PhoneDeviceFactory;
    laptop: typeof LaptopDeviceFactory;
    tablet: typeof TabletDeviceFactory
}

const createFactory = (type: FactoryType): ProductsAbstractFactory => {
    const factories: FactoriesTypes = {
        phone: PhoneDeviceFactory,
        laptop: LaptopDeviceFactory,
        tablet: TabletDeviceFactory
    }

    const Factory = factories[type]
    return new Factory()
}

appDevicesFactory(createFactory('phone'))
appDevicesFactory(createFactory('tablet'))
appDevicesFactory(createFactory('laptop')) 

Mi soluci贸n al reto:

// STEP 1
interface Cpu {
    setSeries(serie: string): void;
}

interface Memory {
    setCapacityInGB(gigaBytes: number): void;
}

interface Display {
    setResolution(): void;
}

// STEP 2
class PhoneCpu implements Cpu {
    public setSeries(serie: string): void {
        console.log(`The CPU of the phone is from the ${serie} series`);
    }
}
class LaptopCpu implements Cpu {
    public setSeries(serie: string): void {
        console.log(`The CPU of the laptop is from the ${serie} series`);
    }
}
class TabletCpu implements Cpu {
    public setSeries(serie: string): void {
        console.log(`The CPU of the tablet is from the ${serie} series`);
    }
}

class PhoneMemory implements Memory {
    public setCapacityInGB(gigaBytes: number): void {
        console.log(`The memory of the phone is ${gigaBytes}GB`);
    }
}
class LaptopMemory implements Memory {
    public setCapacityInGB(gigaBytes: number): void {
        console.log(`The memory of the laptop is ${gigaBytes}GB`);
    }
}
class TabletMemory implements Memory {
    public setCapacityInGB(gigaBytes: number): void {
        console.log(`The memory of the tablet is ${gigaBytes}GB`);
    }
}

class PhoneDisplay implements Display {
    public setResolution(): void {
        console.log(`The phone display is small`);
    }
}
class LaptopDisplay implements Display {
    public setResolution(): void {
        console.log(`The laptop display is big`);
    }
}
class TabletDisplay implements Display {
    public setResolution(): void {
        console.log(`The tablet display is medium`);
    }
}

// STEP 3
interface DevicesAbstractFactory {
    createCpu(): Cpu;
    createMemory(): Memory;
    createDisplay(): Display;
}

// STEP 4
class PhoneFactory implements DevicesAbstractFactory {
    createCpu(): Cpu {
        return new PhoneCpu();
    }
    createMemory(): Memory {
        return new PhoneMemory();
    }
    createDisplay(): Display {
        return new PhoneDisplay();
    }
}
class TabletFactory implements DevicesAbstractFactory {
    createCpu(): Cpu {
        return new TabletCpu();
    }
    createMemory(): Memory {
        return new TabletMemory();
    }
    createDisplay(): Display {
        return new TabletDisplay();
    }
}
class LaptopFactory implements DevicesAbstractFactory {
    createCpu(): Cpu {
        return new LaptopCpu();
    }
    createMemory(): Memory {
        return new LaptopMemory();
    }
    createDisplay(): Display {
        return new LaptopDisplay();
    }
}

function appDeviceFactory(factory: DevicesAbstractFactory) {
    const cpu: Cpu = factory.createCpu();
    const memory: Memory = factory.createMemory();
    const display: Display = factory.createDisplay();

    cpu.setSeries('X');
    memory.setCapacityInGB(128);
    display.setResolution();
}

appDeviceFactory(new LaptopFactory());
appDeviceFactory(new PhoneFactory());
appDeviceFactory(new TabletFactory());

Me di cuenta que en la mayoria de estudiantes que publicaron su codigo lo hicieron de una forma que siempre cuando se instancie alguna familia siempre le seteara los mismos valores, asi que modifique el ejercicio un poco, usando constructores para que quede dinamico y poder crear cada familia con sus valores correspondientes

// STEP 1
interface CPU {
    getSeries(): string
}

interface Memory{
    getCapacityInGB(): void;
}

interface Display{
    getResolution():void;
}

// STEP 2

class CPUPhone implements CPU{
    series:string;
    constructor(series:string){
        this.series = series;
    }
    getSeries(): string {
        return this.series
    }
}

class CPULaptop implements CPU{
    getSeries(): string {
        throw new Error("Method not implemented.");
    }
    setSeries(series: string): void {
        console.log("Series CPU Laptop ->", series)
    }   
}

class CPUTablet implements CPU{
    getSeries(): string {
        throw new Error("Method not implemented.");
    }
    setSeries(series: string): void {
        console.log("Series CPU Tablet ->", series)
    }   
}

class MemoryPhone implements Memory{
    memory:number;
    constructor(memory:number){
        this.memory = memory;
    }
    getCapacityInGB(): number {
        return this.memory
    }
}

class MemoryLaptop implements Memory{
    memory:number;
    constructor(memory:number){
        this.memory = memory;
    }
    getCapacityInGB(): number {
        return this.memory
    }
}

class MemoryTablet implements Memory{
    memory:number;
    constructor(memory:number){
        this.memory = memory;
    }
    getCapacityInGB(): number {
        return this.memory
    }
}

class DisplayPhone implements Display{
    resolution:number;
    constructor(resolution:number){
        this.resolution = resolution;
    }
    getResolution(): number {
        return this.resolution;
    }
}

class DisplayLaptop implements Display{
    resolution:number;
    constructor(resolution:number){
        this.resolution = resolution;
    }
    getResolution(): number {
        return this.resolution;
    }
}

class DisplayTablet implements Display{
    resolution:number;
    constructor(resolution:number){
        this.resolution = resolution;
    }
    getResolution(): number {
        return this.resolution;
    }
}

//Step 3

interface abstractFactory{
    cpu:string,
    memory: number,
    display: number,
    createCPU(): CPU,
    createMemory(): Memory,
    createDisplay(): Display
}

class Phone implements abstractFactory{
    cpu:string;
    memory: number;
    display: number;
    constructor(cpu: string,memory: number,display: number){
        this.cpu = cpu;
        this.memory = memory;
        this.display = display;
    }

    createCPU(): CPU {
        return new CPUPhone(this.cpu)
    }
    createMemory(): Memory {
        return new MemoryPhone(this.memory);
    }
    createDisplay(): Display {
        return new DisplayPhone(this.display);
    } 
}

class Tablet implements abstractFactory{
    cpu:string;
    memory: number;
    display: number;
    constructor(cpu: string,memory: number,display: number){
        this.cpu = cpu;
        this.memory = memory;
        this.display = display;
    }

    createCPU(): CPU {
        return new CPUPhone(this.cpu)
    }
    createMemory(): Memory {
        return new MemoryPhone(this.memory);
    }
    createDisplay(): Display {
        return new DisplayPhone(this.display);
    } 
}

function app(factory:abstractFactory){
    const cpu = factory.createCPU()
    console.log("Cpu ",cpu.getSeries())

    const memory = factory.createMemory()
    console.log("Memory ", memory.getCapacityInGB())

    const display = factory.createDisplay()
    console.log("Display ", display.getResolution())
}

app(new Phone("m1", 128, 1200))
app(new Tablet("m2",512, 2200))

Existe otro patr贸n de dise帽o que podr铆a resolver la necesidad de crear m煤ltiples productos y tipos de productos teniendo en cuenta su jerarqu铆a, se conoce como Composite, comparto un enlace para que lo revisen.

Tuve que leer la respuesta para entender un poco, estaba confundido por donde empezar

// Step 1
class CPU {
    setSeries(series) {
        throw new Error("Not implemented");
    }
}
class Memory {    
    setCapacityInGB(capacity) {
        throw new Error("Not implemented");
    }
}
class Display {    
    setResolution(resolution) {
        throw new Error("Not implemented");
    }
}

// Step 2
//CP
class PhoneCPU extends CPU {
    setSeries(series) {
        console.log(`[PHONE] ${series}`);
    }    
}
class LaptopCPU extends CPU {
    setSeries(series) {
        console.log(`[LAPTOP] ${series}`);
    }    
}
class TabletCPU extends CPU {
    setSeries(series) {
        console.log(`[TABLET] ${series}`);
    }    
}
//Memory
class PhoneMemory extends Memory {
    setCapacityInGB(capacity) {
        console.log(`[PHONE] ${capacity}`);
    }    
}
class LaptopMemory extends Memory {
    setCapacityInGB(capacity) {
        console.log(`[LAPTOP] ${capacity}`);
    }    
}
class TabletMemory extends Memory {
    setCapacityInGB(capacity) {
        console.log(`[TABLET] ${capacity}`);
    }    
}
// Resolution
class PhoneResolution extends Display{
    setResolution(resolution) {
        console.log(`[PHONE] ${resolution}`);
    }    
}
class LaptopResolution extends Display{
    setResolution(resolution) {
        console.log(`[LAPTOP] ${resolution}`);
    }    
}
class TabletResolution extends Display{
    setResolution(resolution) {
        console.log(`[TABLET] ${resolution}`);
    }    
}

//Step 3
class DeviceFactory {
    createCPU() {
        throw new Error('Method not implemented!');
    }
    createMemory() {
        throw new Error('Method not implemented!');
    }
    createDisplay() {
        throw new Error('Method not implemented!');
    }
}

class PhoneDeviceFactory extends DeviceFactory {
    createCPU() {
        return new PhoneCPU();
    }
    createMemory() {
        return new PhoneMemory();
    }
    createDisplay() {
        return new PhoneResolution();
    }
}
class LaptopDeviceFactory extends DeviceFactory {
    createCPU() {
        return new LaptopCPU();
    }
    createMemory() {
        return new LaptopMemory();
    }
    createDisplay() {
        return new LaptopResolution();
    }
}
class TabletDeviceFactory extends DeviceFactory {
    createCPU() {
        return new TabletCPU();
    }
    createMemory() {
        return new TabletMemory();
    }
    createDisplay() {
        return new TabletResolution();
    }
}

function appAbstractFactory({factory, cpuSeries, capacity, resolution}) {    
    if (!factory) {
        console.log('---No factory provided ---');
        return '---No factory provided ---'
    }

    const cpu = factory.createCPU();
    const memory = factory.createMemory();
    const display = factory.createDisplay();

    cpu.setSeries(cpuSeries);
    memory.setCapacityInGB(capacity);
    display.setResolution(resolution)
}

function createFactory(deviceTyoe) {
    const devices = {
        'phone': PhoneDeviceFactory,
        'laptop': LaptopDeviceFactory,
        'tablet': TabletDeviceFactory
    }
    const Devices = devices[deviceTyoe];
    return new Devices();
}

appAbstractFactory({
    factory: createFactory('phone'),
    cpuSeries: 'Snapdragon 690',
    capacity: 16,
    resolution: '2560x1440',
})
appAbstractFactory({
    factory: createFactory('laptop'),
    cpuSeries: 'Intel Core i9',
    capacity: 500,
    resolution: '1920x1080',
})
appAbstractFactory({
    factory: createFactory('tablet'),
    cpuSeries: 'ARM Cortex-A53',
    capacity: 64,
    resolution: '1280x720',
})```

Soluci贸n 馃槃鈥

.
.
.
.

interface Cpu {
  setSeries(series: string): void;
}

interface Memory {
  setCapacityInGB(capacity: number): void;
}

interface Display {
  setResolution(): void;
}

class PhoneCpu implements Cpu {
  setSeries(series: string): void {
    console.log(`[Phone] CPU's series: ${series}`);
  }
}

class LaptopCpu implements Cpu {
  setSeries(series: string): void {
    console.log(`[Laptop] CPU's series: ${series}`);
  }
}

class TabletCpu implements Cpu {
  setSeries(series: string): void {
    console.log(`[Tablet] CPU series: ${series}`);
  }
}

class PhoneMemory implements Memory {
  setCapacityInGB(capacity: number): void {
    console.log(`[Phone] Memory capacity: ${capacity}`);
  }
}

class LaptopMemory implements Memory {
  setCapacityInGB(capacity: number): void {
    console.log(`[Laptop] Memory capacity: ${capacity}`);
  }
}

class TabletMemory implements Memory {
  setCapacityInGB(capacity: number): void {
    console.log(`[Tablet] Memory capacity: ${capacity}`);
  }
}

class PhoneDisplay implements Display {
  setResolution(): void {
    console.log(`[Phone] Display`);
  }
}

class LaptopDisplay implements Display {
  setResolution(): void {
    console.log(`[Laptop] Display`);
  }
}

class TabletDisplay implements Display {
  setResolution(): void {
    console.log(`[Tablet] Display`);
  }
}

interface componentAbstractFactory {
  createCpu(): Cpu;
  createMemory(): Memory;
  createDisplay(): Display;
}

class PhoneComponentFactory implements componentAbstractFactory {
  createCpu(): Cpu {
    return new PhoneCpu();
  }

  createMemory(): Memory {
    return new PhoneMemory();
  }

  createDisplay(): Display {
    return new PhoneDisplay();
  }
}

class LaptopComponentFactory implements componentAbstractFactory {
  createCpu(): Cpu {
    return new LaptopCpu();
  }

  createMemory(): Memory {
    return new LaptopMemory();
  }

  createDisplay(): Display {
    return new LaptopDisplay();
  }
}

class TabletComponentFactory implements componentAbstractFactory {
  createCpu(): Cpu {
    return new TabletCpu();
  }

  createMemory(): Memory {
    return new TabletMemory();
  }

  createDisplay(): Display {
    return new TabletDisplay();
  }
}

function appComponentFactory(
  factory: componentAbstractFactory,
  series: string,
  capacity: number
) {
  const cpu: Cpu = factory.createCpu();
  const memory: Memory = factory.createMemory();
  const display: Display = factory.createDisplay();

  cpu.setSeries(series);
  memory.setCapacityInGB(capacity);
  display.setResolution();
}

// appComponentFactory(new PhoneComponentFactory(), "X-Phone-Series", 15);
// appComponentFactory(new LaptopComponentFactory(), "Y-Laptop-Series", 23);
// appComponentFactory(new TabletComponentFactory(), "Z-Tablet-Series", 39);

type FactoryType = "phone" | "laptop" | "tablet";
function createFactory(type: FactoryType): componentAbstractFactory {
  const factories = {
    phone: PhoneComponentFactory,
    laptop: LaptopComponentFactory,
    tablet: TabletComponentFactory,
  };
  const Factory = factories[type];
  return new Factory();
}

appComponentFactory(createFactory("phone"), "X-Phone-Series", 15);
appComponentFactory(createFactory("laptop"), "Y-Laptop-Series", 23);
appComponentFactory(createFactory("tablet"), "Z-Tablet-Series", 39);

Los patrones de dise帽o creacionales, como el patr贸n Factory (f谩brica) y Abstract Factory (f谩brica abstracta), est谩n estrechamente relacionados con los principios SOLID, especialmente con el principio de Inversi贸n de Dependencias (Dependency Inversion Principle - DIP).
.
El principio de Inversi贸n de Dependencias establece que:
.

  1. Los m贸dulos de alto nivel no deben depender de los m贸dulos de bajo nivel. Ambos deben depender de abstracciones.
    .

  2. Las abstracciones no deben depender de detalles. Los detalles deben depender de abstracciones.

.
Los patrones Factory y Abstract Factory est谩n dise帽ados para ayudar a aplicar este principio, ya que introducen una capa de abstracci贸n entre el c贸digo que necesita objetos y las clases concretas que los crean.
.

  • Factory Method Pattern (Patr贸n de M茅todo de F谩brica): Permite definir una interfaz para crear un objeto, pero delega la decisi贸n de qu茅 clase concreta implementar al subclase. As铆, los objetos se crean a trav茅s de un m茅todo com煤n pero las subclases pueden proporcionar la implementaci贸n espec铆fica.
    .

  • Abstract Factory Pattern (Patr贸n de F谩brica Abstracta): Proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. Esto permite la creaci贸n de objetos relacionados sin exponer las implementaciones concretas al c贸digo que los utiliza.

.
Ambos patrones promueven la idea de trabajar con abstracciones en lugar de clases concretas, lo que facilita la adhesi贸n al principio de Inversi贸n de Dependencias de SOLID. Al utilizar estos patrones, el c贸digo de alto nivel puede interactuar con interfaces o clases abstractas, evitando depender directamente de implementaciones concretas. Esto facilita la flexibilidad, el mantenimiento y la extensi贸n del c贸digo, ya que los cambios en las implementaciones concretas no afectar谩n al c贸digo que depende de las abstracciones.

TS code.

// Base interface Products
interface CPU {
    setSeries(string:string): void;
}

interface Memory {
    setCapacityInGB(number:number): void;
}

interface Display {
    setResoltion(): void;
}

// Concrete CPU Class Products for each family
class CPUforPhone implements CPU {
    setSeries(string: string): void {
        console.log(`Cpu serie ${string} for Phone`);
    }
}

class CPUforLaptop implements CPU {
    setSeries(string: string): void {
        console.log(`Cpu serie ${string} for Laptop`);
    }
}

class CPUforTablet implements CPU {
    setSeries(string: string): void {
        console.log(`Cpu serie ${string} for Tablet`);
    }
}


// Concrete Memory Class Products for each family
class MemoryForPhone implements Memory{
    setCapacityInGB(number: number): void {
        console.log(`Phone memory is ${number} GB`);  
    }
}

class MemoryForLaptop implements Memory{
    setCapacityInGB(number: number): void {
        console.log(`Laptop memory is ${number} GB`);  
    }
}

class MemoryForTablet implements Memory{
    setCapacityInGB(number: number): void {
        console.log(`Tablet memory is ${number} GB`);
    }
}


// Concrete Display Class Products for each family
class DisplayForPhone implements Display {
    setResoltion(): void {
        console.log(`Resolution for Phone`);
    }
}

class DisplayForLaptop implements Display {
    setResoltion(): void {
        console.log(`Resolution for Laptop`);
    }
}

class DisplayForTablet implements Display {
    setResoltion(): void {
        console.log(`Resolution for Tablet`);
    }
}


// Create abstract factory
interface TechFactory {
    createCpu(): CPU; 
    createMemory(): Memory; 
    createDisplay(): Display;
}


// Factory of phones
class PhoneFactory implements TechFactory {
    createCpu(): CPU {
        return new CPUforPhone; 
    }

    createMemory(): Memory {
        return new MemoryForPhone;
    }

    createDisplay(): Display {
        return new DisplayForPhone;
    }
}

// Factory of Laptops
class LaptopFactory implements TechFactory {
    createCpu(): CPU {
        return new CPUforLaptop; 
    }

    createMemory(): Memory {
        return new MemoryForLaptop;
    }

    createDisplay(): Display {
        return new DisplayForLaptop;
    }
}

// Factory of tablets
class TabletFactory implements TechFactory {
    createCpu(): CPU {
        return new CPUforTablet; 
    }

    createMemory(): Memory {
        return new MemoryForTablet;
    }

    createDisplay(): Display {
        return new DisplayForTablet;
    }
}

// implementation
type factoryType = 'phone' | 'laptop' | 'tablet';

function createFactory(factory: factoryType): TechFactory {
    const factories = {
        'phone': PhoneFactory,
        'laptop': LaptopFactory,
        'tablet': TabletFactory
    };

    const Factory = new factories[factory];

    return Factory;
};

function createProduct(factory: TechFactory) {
    const CPU: CPU = factory.createCpu();
    const memory: Memory = factory.createMemory();
    const display: Display = factory.createDisplay();

    CPU.setSeries('V1');
    memory.setCapacityInGB(16);
    display.setResoltion();
};

createProduct(createFactory('phone'));
createProduct(createFactory('laptop'));
createProduct(createFactory('tablet'));

Hice el reto aprovechando los m贸dulos es ESM. Los invito a que le echen un ojo para tomar ideas o dar feedback 馃
https://github.com/realDiegoR/ts-design-patterns/tree/main/abstract-factory
(Denle a la tecla (.) para abrir GitHub Codespaces para visualizar mejor mejor)

隆Hola! Con respecto a la contra de que si se realiza un cambio al elemento base, todos los productos concretos deben de implementar el cambio, hay que tener en cuenta que si se desean seguir los principios SOLID, podr铆a no aplicarse del todo ante alg煤n cambio, especificamente con el principio I de segregaci贸n de interfaces, ejemplo, la clase base MastodonCar se le implementar谩 un nuevo m茅todo que es 鈥淎uto-conducci贸n鈥, al ser una interfaz o una clase base, este m茅todo deber铆a de ir tanto en MastodonSedanCar y MastodonHatchbackCar, 隆Pero hey! Tenemos un l铆o y es que el Hatchback no cuenta con esta funcionalidad, por lo que le estar铆amos aplicando un m茅todo que NO necesita tener implementado, por lo que ser铆a necesario quiz谩s refactorizar el c贸digo ya que el principio I dice que no debemos de implementar m茅todos que una clase no necesita, dividiendo la interfaz en dos interfaces como 鈥淢astodonCarWithIA鈥 y 鈥淢astodonCarWithoutIA鈥 podr铆amos ya estar empezando a salirnos del patr贸n de dise帽o, as铆 que ser铆a necesario crear una nueva clase base y por ende, m谩s c贸digo gen茅rico.

De solo pensar como ese peque帽o cambio podr铆a afectar el programa, me dio dolor de cabeza 馃槄

Excelente clase y desafio, les comparto mi soluci贸n en JS: ```js // step 1 > Base products class CPUBase { setSeries(){ return new Error ('Method CPUBase not implemented.'); } }; class DisplayBase { setResolution(resolution){ return new Error ('Method CPUBase not implemented.'); } } class MemoryBase { setCapacityInGb(gb){ return new Error ('Method CPUBase not implemented.'); } } //step 2 > Concrete products class CPU extends CPUBase { setSeries(numberSeries) { console.log(`CPU: ${numberSeries}`); } } class Display extends DisplayBase { setResolution(resolution) { console.log(`Display: ${resolution}`); } } class Memory extends MemoryBase { setCapacityInGb(gb) { console.log(`GB: ${gb}`); } } //step 3 > Concrete factory class DeviceAbstractFactory { makeCPU() { throw new Error('Method makeCPU not implemented.'); } makeDisplay(){ throw new Error('Method makeDisplay not implemented.'); } makeMemory(){ throw new Error('Method makeMemory not implemented.'); } } //step 4 > Concrete factories class PhoneFactory extends DeviceAbstractFactory { makeCPU() { return new CPU(); } makeDisplay() { return new Display(); } makeMemory() { return new Memory(); } } class LaptopFactory extends DeviceAbstractFactory { makeCPU() { return new CPU(); } makeDisplay() { return new Display(); } makeMemory() { return new Memory(); } } class TabletFactory extends DeviceAbstractFactory { makeCPU() { return new CPU(); } makeDisplay() { return new Display(); } makeMemory() { return new Memory(); } } //step 5: use function appFactory(factory, cpu, ram, resolution){ const makeCpu = factory.makeCPU(); const makeDisplay = factory.makeDisplay(); const makeMemory = factory.makeMemory(); makeCpu.setSeries(cpu); makeDisplay.setResolution(resolution); makeMemory.setCapacityInGb(ram); } function createFactory(type) { const factories = { laptop: LaptopFactory, phone: PhoneFactory, tablet: TabletFactory, }; const Factory = factories[type]; return new Factory; }; appFactory(createFactory('laptop'), 'Intel i3', 4, '4k'); appFactory(createFactory('phone'), 'AMD 7', 8, '2k'); appFactory(createFactory('tablet'), 'SnapDragon', 16, '8k'); ```// step 1 > Base productsclass CPUBase { setSeries(){ return new Error ('Method CPUBase not implemented.'); }}; class DisplayBase { setResolution(resolution){ return new Error ('Method CPUBase not implemented.'); }} class MemoryBase { setCapacityInGb(gb){ return new Error ('Method CPUBase not implemented.'); }} //step 2 > Concrete productsclass CPU extends CPUBase { setSeries(numberSeries) { console.log(`CPU: ${numberSeries}`); }} class Display extends DisplayBase { setResolution(resolution) { console.log(`Display: ${resolution}`); }} class Memory extends MemoryBase { setCapacityInGb(gb) { console.log(`GB: ${gb}`); }} //step 3 > Concrete factoryclass DeviceAbstractFactory { makeCPU() { throw new Error('Method makeCPU not implemented.'); } makeDisplay(){ throw new Error('Method makeDisplay not implemented.'); } makeMemory(){ throw new Error('Method makeMemory not implemented.'); } } //step 4 > Concrete factoriesclass PhoneFactory extends DeviceAbstractFactory { makeCPU() { return new CPU(); } makeDisplay() { return new Display(); } makeMemory() { return new Memory(); }} class LaptopFactory extends DeviceAbstractFactory { makeCPU() { return new CPU(); } makeDisplay() { return new Display(); } makeMemory() { return new Memory(); }} class TabletFactory extends DeviceAbstractFactory { makeCPU() { return new CPU(); } makeDisplay() { return new Display(); } makeMemory() { return new Memory(); }} //step 5: usefunction appFactory(factory, cpu, ram, resolution){ const makeCpu = factory.makeCPU(); const makeDisplay = factory.makeDisplay(); const makeMemory = factory.makeMemory(); makeCpu.setSeries(cpu); makeDisplay.setResolution(resolution); makeMemory.setCapacityInGb(ram);} function createFactory(type) { const factories = { laptop: LaptopFactory, phone: PhoneFactory, tablet: TabletFactory, }; const Factory = factories\[type]; return new Factory;}; appFactory(createFactory('laptop'), 'Intel i3', 4, '4k');appFactory(createFactory('phone'), 'AMD 7', 8, '2k');appFactory(createFactory('tablet'), 'SnapDragon', 16, '8k');
Adjunto resultado del reto en JS ````js // Step 1 class CPU { setSeries(series) { throw new Error("Not implemented"); } } class Memory { setCapacityInGB(capacity) { throw new Error("Not implemented"); } } class Display { setResolution(resolution) { throw new Error("Not implemented"); } } // Step 2 //CP class PhoneCPU extends CPU { setSeries(series) { console.log(`[PHONE] ${series}`); } } class LaptopCPU extends CPU { setSeries(series) { console.log(`[LAPTOP] ${series}`); } } class TabletCPU extends CPU { setSeries(series) { console.log(`[TABLET] ${series}`); } } //Memory class PhoneMemory extends Memory { setCapacityInGB(capacity) { console.log(`[PHONE] ${capacity}`); } } class LaptopMemory extends Memory { setCapacityInGB(capacity) { console.log(`[LAPTOP] ${capacity}`); } } class TabletMemory extends Memory { setCapacityInGB(capacity) { console.log(`[TABLET] ${capacity}`); } } // Resolution class PhoneResolution extends Display{ setResolution(resolution) { console.log(`[PHONE] ${resolution}`); } } class LaptopResolution extends Display{ setResolution(resolution) { console.log(`[LAPTOP] ${resolution}`); } } class TabletResolution extends Display{ setResolution(resolution) { console.log(`[TABLET] ${resolution}`); } } //Step 3 class DeviceFactory { createCPU() { throw new Error('Method not implemented!'); } createMemory() { throw new Error('Method not implemented!'); } createDisplay() { throw new Error('Method not implemented!'); } } class PhoneDeviceFactory extends DeviceFactory {a createCPU() { return new PhoneCPU(); } createMemory() { return new PhoneMemory(); } createDisplay() { return new PhoneResolution(); } } class LaptopDeviceFactory extends DeviceFactory { createCPU() { return new LaptopCPU(); } createMemory() { return new LaptopMemory(); } createDisplay() { return new LaptopResolution(); } } class TabletDeviceFactory extends DeviceFactory { createCPU() { return new TabletCPU(); } createMemory() { return new TabletMemory(); } createDisplay() { return new TabletResolution(); } } function appAbstractFactory({factory, cpuSeries, capacity, resolution}) { if (!factory) { console.log('---No factory provided ---'); return '---No factory provided ---' } const cpu = factory.createCPU(); const memory = factory.createMemory(); const display = factory.createDisplay(); cpu.setSeries(cpuSeries); memory.setCapacityInGB(capacity); display.setResolution(resolution) } function createFactory(deviceTyoe) { const devices = { 'phone': PhoneDeviceFactory, 'laptop': LaptopDeviceFactory, 'tablet': TabletDeviceFactory } const Devices = devices[deviceTyoe]; return new Devices(); } appAbstractFactory({ factory: createFactory('phone'), cpuSeries: 'Snapdragon 690', capacity: 16, resolution: '2560x1440', }) appAbstractFactory({ factory: createFactory('laptop'), cpuSeries: 'Intel Core i9', capacity: 500, resolution: '1920x1080', }) appAbstractFactory({ factory: createFactory('tablet'), cpuSeries: 'ARM Cortex-A53', capacity: 64, resolution: '1280x720', }) ```// Step 1class CPU { setSeries(series) { throw new Error("Not implemented"); }}class Memory { setCapacityInGB(capacity) { throw new Error("Not implemented"); }}class Display { setResolution(resolution) { throw new Error("Not implemented"); }} // Step 2//CPclass PhoneCPU extends CPU { setSeries(series) { console.log(`\[PHONE] ${series}`); } }class LaptopCPU extends CPU { setSeries(series) { console.log(`\[LAPTOP] ${series}`); } }class TabletCPU extends CPU { setSeries(series) { console.log(`\[TABLET] ${series}`); } }//Memoryclass PhoneMemory extends Memory { setCapacityInGB(capacity) { console.log(`\[PHONE] ${capacity}`); } }class LaptopMemory extends Memory { setCapacityInGB(capacity) { console.log(`\[LAPTOP] ${capacity}`); } }class TabletMemory extends Memory { setCapacityInGB(capacity) { console.log(`\[TABLET] ${capacity}`); } }// Resolutionclass PhoneResolution extends Display{ setResolution(resolution) { console.log(`\[PHONE] ${resolution}`); } }class LaptopResolution extends Display{ setResolution(resolution) { console.log(`\[LAPTOP] ${resolution}`); } }class TabletResolution extends Display{ setResolution(resolution) { console.log(`\[TABLET] ${resolution}`); } } //Step 3class DeviceFactory { createCPU() { throw new Error('Method not implemented!'); } createMemory() { throw new Error('Method not implemented!'); } createDisplay() { throw new Error('Method not implemented!'); }} class PhoneDeviceFactory extends DeviceFactory {a createCPU() { return new PhoneCPU(); } createMemory() { return new PhoneMemory(); } createDisplay() { return new PhoneResolution(); }}class LaptopDeviceFactory extends DeviceFactory { createCPU() { return new LaptopCPU(); } createMemory() { return new LaptopMemory(); } createDisplay() { return new LaptopResolution(); }}class TabletDeviceFactory extends DeviceFactory { createCPU() { return new TabletCPU(); } createMemory() { return new TabletMemory(); } createDisplay() { return new TabletResolution(); }} function appAbstractFactory({factory, cpuSeries, capacity, resolution}) { if (!factory) { console.log('---No factory provided ---'); return '---No factory provided ---' } const cpu = factory.createCPU(); const memory = factory.createMemory(); const display = factory.createDisplay(); cpu.setSeries(cpuSeries); memory.setCapacityInGB(capacity); display.setResolution(resolution)} function createFactory(deviceTyoe) { const devices = { 'phone': PhoneDeviceFactory, 'laptop': LaptopDeviceFactory, 'tablet': TabletDeviceFactory } const Devices = devices\[deviceTyoe]; return new Devices();} appAbstractFactory({ factory: createFactory('phone'), cpuSeries: 'Snapdragon 690', capacity: 16, resolution: '2560x1440',})appAbstractFactory({ factory: createFactory('laptop'), cpuSeries: 'Intel Core i9', capacity: 500, resolution: '1920x1080',})appAbstractFactory({ factory: createFactory('tablet'), cpuSeries: 'ARM Cortex-A53', capacity: 64, resolution: '1280x720',}) ````
```js class CPU { setSeries(serie){ console.log(`CPU series is set to ${serie}`); } } class Memory { setCapacityInGB(capacity){ console.log(`Memory capacity is set to ${capacity} GB`); } } class Display { setResolution(resolution){ console.log(`Display resolution is set to ${resolution}`); } } class AbstractFactory { createCPU() {} createMemory() {} createDisplay() {} } class PhoneFactory extends AbstractFactory { createCPU() { return new CPU(); } createMemory() { return new Memory(); } createDisplay() { return new Display(); } } class LaptopFactory extends AbstractFactory { createCPU() { return new CPU(); } createMemory() { return new Memory(); } createDisplay() { return new Display(); } } class TabletFactory extends AbstractFactory { createCPU() { return new CPU(); } createMemory() { return new Memory(); } createDisplay() { return new Display(); } } function clientCode(factory, cpuValue, memoryValue, displayValue) { const cpu = factory.createCPU(); cpu.setSeries(cpuValue); const memory = factory.createMemory(); memory.setCapacityInGB(memoryValue); const display = factory.createDisplay(); display.setResolution(displayValue); } const phoneFactory = new PhoneFactory(); clientCode(phoneFactory, 'Snapdragon', 8, '1080x1920'); const laptopFactory = new LaptopFactory(); clientCode(laptopFactory, 'Intel', 16, '1920x1080'); const tabletFactory = new TabletFactory(); clientCode(tabletFactory, 'Snapdragon', 4, '800x1280'); ```class CPU {聽 聽 setSeries(serie){聽 聽 聽 聽 console.log(`CPU series is set to ${serie}`);聽 聽 }} class Memory {聽 聽 setCapacityInGB(capacity){聽 聽 聽 聽 console.log(`Memory capacity is set to ${capacity} GB`);聽 聽 }} class Display {聽 聽 setResolution(resolution){聽 聽 聽 聽 console.log(`Display resolution is set to ${resolution}`);聽 聽 }} class AbstractFactory {聽 聽 createCPU() {}聽 聽 createMemory() {}聽 聽 createDisplay() {}} class PhoneFactory extends AbstractFactory {聽 聽 createCPU() {聽 聽 聽 聽 return new CPU();聽 聽 } 聽 聽 createMemory() {聽 聽 聽 聽 return new Memory();聽 聽 } 聽 聽 createDisplay() {聽 聽 聽 聽 return new Display();聽 聽 }} class LaptopFactory extends AbstractFactory {聽 聽 createCPU() {聽 聽 聽 聽 return new CPU();聽 聽 } 聽 聽 createMemory() {聽 聽 聽 聽 return new Memory();聽 聽 } 聽 聽 createDisplay() {聽 聽 聽 聽 return new Display();聽 聽 }} class TabletFactory extends AbstractFactory {聽 聽 createCPU() {聽 聽 聽 聽 return new CPU();聽 聽 } 聽 聽 createMemory() {聽 聽 聽 聽 return new Memory();聽 聽 } 聽 聽 createDisplay() {聽 聽 聽 聽 return new Display();聽 聽 }} function clientCode(factory, cpuValue, memoryValue, displayValue) {聽 聽 const cpu = factory.createCPU();聽 聽 cpu.setSeries(cpuValue); 聽 聽 const memory = factory.createMemory();聽 聽 memory.setCapacityInGB(memoryValue); 聽 聽 const display = factory.createDisplay();聽 聽 display.setResolution(displayValue);} const phoneFactory = new PhoneFactory();clientCode(phoneFactory, 'Snapdragon', 8, '1080x1920'); const laptopFactory = new LaptopFactory();clientCode(laptopFactory, 'Intel', 16, '1920x1080'); const tabletFactory = new TabletFactory();clientCode(tabletFactory, 'Snapdragon', 4, '800x1280');
class CPU {聽 聽 setSeries(serie){聽 聽 聽 聽 console.log(`CPU series is set to ${serie}`);聽 聽 }} class Memory {聽 聽 setCapacityInGB(capacity){聽 聽 聽 聽 console.log(`Memory capacity is set to ${capacity} GB`);聽 聽 }} class Display {聽 聽 setResolution(resolution){聽 聽 聽 聽 console.log(`Display resolution is set to ${resolution}`);聽 聽 }} class AbstractFactory {聽 聽 createCPU() {}聽 聽 createMemory() {}聽 聽 createDisplay() {}} class PhoneFactory extends AbstractFactory {聽 聽 createCPU() {聽 聽 聽 聽 return new CPU();聽 聽 } 聽 聽 createMemory() {聽 聽 聽 聽 return new Memory();聽 聽 } 聽 聽 createDisplay() {聽 聽 聽 聽 return new Display();聽 聽 }} class LaptopFactory extends AbstractFactory {聽 聽 createCPU() {聽 聽 聽 聽 return new CPU();聽 聽 } 聽 聽 createMemory() {聽 聽 聽 聽 return new Memory();聽 聽 } 聽 聽 createDisplay() {聽 聽 聽 聽 return new Display();聽 聽 }} class TabletFactory extends AbstractFactory {聽 聽 createCPU() {聽 聽 聽 聽 return new CPU();聽 聽 } 聽 聽 createMemory() {聽 聽 聽 聽 return new Memory();聽 聽 } 聽 聽 createDisplay() {聽 聽 聽 聽 return new Display();聽 聽 }} function clientCode(factory, cpuValue, memoryValue, displayValue) {聽 聽 const cpu = factory.createCPU();聽 聽 cpu.setSeries(cpuValue); 聽 聽 const memory = factory.createMemory();聽 聽 memory.setCapacityInGB(memoryValue); 聽 聽 const display = factory.createDisplay();聽 聽 display.setResolution(displayValue);} const phoneFactory = new PhoneFactory();clientCode(phoneFactory, 'Snapdragon', 8, '1080x1920'); const laptopFactory = new LaptopFactory();clientCode(laptopFactory, 'Intel', 16, '1920x1080'); const tabletFactory = new TabletFactory();clientCode(tabletFactory, 'Snapdragon', 4, '800x1280');
XD Yo hice un ejemplo de zombies XDDDDDDDDDDDD \------------------------- ```js // BASE class HeadZombie { useRenderHeads() { throw new Error('Method not implemented') } } class ArmsZombie { useRenderArms() { throw new Error('Method not implemented') } } class ShirtZombie { useRenderShirt() { throw new Error('Method not implemented') } } class ShoesZombie { useRenderShoes(){ throw new Error('Method not implemented') } } class TypeZombie { setTypeZombie(){ throw new Error('Method not implemented') } } // COMPORTAMIENTOS INDIVIDUALES // HEAD class HeadZombieDestroyed extends HeadZombie { useRenderHeads() { return 'HeadZombieDestroyed' } } class HeadZombieNew extends HeadZombie { useRenderHeads() { return 'HeadZombieNew' } } class HeadZombiePartial extends HeadZombie { useRenderHeads() { return 'HeadZombiePartial' } } // ARMS class ArmsZombieIntact extends ArmsZombie { useRenderArms() { return 'ArmsZombieIntact'; } } class ArmsZombieBroken extends ArmsZombie { useRenderArms() { return 'ArmsZombieBroken'; } } class ArmsZombieMissing extends ArmsZombie { useRenderArms() { return 'ArmsZombieMissing'; } } // SHIRT class ShirtZombieTattered extends ShirtZombie { useRenderShirt() { return 'ShirtZombieTattered'; } } class ShirtZombieBloody extends ShirtZombie { useRenderShirt() { return 'ShirtZombieBloody'; } } class ShirtZombieClean extends ShirtZombie { useRenderShirt() { return 'ShirtZombieClean'; } } // SHOES class ShoesZombieOld extends ShoesZombie { useRenderShoes() { return 'ShoesZombieOld'; } } class ShoesZombieTorn extends ShoesZombie { useRenderShoes() { return 'ShoesZombieTorn'; } } class ShoesZombieMissing extends ShoesZombie { useRenderShoes() { return 'ShoesZombieMissing'; } } // TYPE class TypeZombieWalker extends TypeZombie { setTypeZombie() { return 'TypeZombieWalker'; } } class TypeZombieRunner extends TypeZombie { setTypeZombie() { return 'TypeZombieRunner'; } } class TypeZombieCrawler extends TypeZombie { setTypeZombie() { return 'TypeZombieCrawler'; } } // FACTORY class ZombieAbstractFactory { createHead(){ throw new Error('Method not implemented') } createArms(){ throw new Error('Method not implemented') } createShirt(){ throw new Error('Method not implemented') } createShoes(){ throw new Error('Method not implemented') } createType(){ throw new Error('Method not implemented') } } // NEW ZOMBIES class ZombieRunnerWornOut extends ZombieAbstractFactory{ createHead() { return new HeadZombieDestroyed()} createArms() { return new ArmsZombieBroken()} createShirt() { return new ShirtZombieTattered()} createShoes() { return new ShoesZombieOld()} createType() { return new TypeZombieRunner()} } class ZombieWalkerNew extends ZombieAbstractFactory { createHead() { return new HeadZombieNew(); } createArms() { return new ArmsZombieIntact(); } createShirt() { return new ShirtZombieClean(); } createShoes() { return new ShoesZombieNew(); } createType() { return new TypeZombieWalker(); } } class ZombieCrawlerTattered extends ZombieAbstractFactory { createHead() { return new HeadZombiePartial(); } createArms() { return new ArmsZombieMissing(); } createShirt() { return new ShirtZombieBloody(); } createShoes() { return new ShoesZombieTorn(); } createType() { return new TypeZombieCrawler(); } } class ZombieRunnerIntact extends ZombieAbstractFactory { createHead() { return new HeadZombieNew(); } createArms() { return new ArmsZombieIntact(); } createShirt() { return new ShirtZombieClean(); } createShoes() { return new ShoesZombieNew(); } createType() { return new TypeZombieRunner(); } } class ZombieWalkerDestroyed extends ZombieAbstractFactory { createHead() { return new HeadZombieDestroyed(); } createArms() { return new ArmsZombieBroken(); } createShirt() { return new ShirtZombieTattered(); } createShoes() { return new ShoesZombieOld(); } createType() { return new TypeZombieWalker(); } } class ZombieCrawlerNew extends ZombieAbstractFactory { createHead() { return new HeadZombieNew(); } createArms() { return new ArmsZombieIntact(); } createShirt() { return new ShirtZombieClean(); } createShoes() { return new ShoesZombieNew(); } createType() { return new TypeZombieCrawler(); } } class ZombieRunnerBloody extends ZombieAbstractFactory { createHead() { return new HeadZombiePartial(); } createArms() { return new ArmsZombieMissing(); } createShirt() { return new ShirtZombieBloody(); } createShoes() { return new ShoesZombieTorn(); } createType() { return new TypeZombieRunner(); } } class ZombieWalkerPartial extends ZombieAbstractFactory { createHead() { return new HeadZombiePartial(); } createArms() { return new ArmsZombieBroken(); } createShirt() { return new ShirtZombieBloody(); } createShoes() { return new ShoesZombieTorn(); } createType() { return new TypeZombieWalker(); } } class ZombieCrawlerOld extends ZombieAbstractFactory { createHead() { return new HeadZombieDestroyed(); } createArms() { return new ArmsZombieMissing(); } createShirt() { return new ShirtZombieTattered(); } createShoes() { return new ShoesZombieOld(); } createType() { return new TypeZombieCrawler(); } } class ZombieRunnerTattered extends ZombieAbstractFactory { createHead() { return new HeadZombiePartial(); } createArms() { return new ArmsZombieBroken(); } createShirt() { return new ShirtZombieTattered(); } createShoes() { return new ShoesZombieTorn(); } createType() { return new TypeZombieRunner(); } } class ZombieWalkerBloody extends ZombieAbstractFactory { createHead() { return new HeadZombieNew(); } createArms() { return new ArmsZombieIntact(); } createShirt() { return new ShirtZombieBloody(); } createShoes() { return new ShoesZombieNew(); } createType() { return new TypeZombieWalker(); } } class ZombieCrawlerBroken extends ZombieAbstractFactory { createHead() { return new HeadZombieDestroyed(); } createArms() { return new ArmsZombieBroken(); } createShirt() { return new ShirtZombieTattered(); } createShoes() { return new ShoesZombieOld(); } createType() { return new TypeZombieCrawler(); } } class ZombieRunnerClean extends ZombieAbstractFactory { createHead() { return new HeadZombieNew(); } createArms() { return new ArmsZombieIntact(); } createShirt() { return new ShirtZombieClean(); } createShoes() { return new ShoesZombieNew(); } createType() { return new TypeZombieRunner(); } } class ZombieWalkerMissing extends ZombieAbstractFactory { createHead() { return new HeadZombiePartial(); } createArms() { return new ArmsZombieMissing(); } createShirt() { return new ShirtZombieBloody(); } createShoes() { return new ShoesZombieTorn(); } createType() { return new TypeZombieWalker(); } } class ZombieCrawlerIntact extends ZombieAbstractFactory { createHead() { return new HeadZombieNew(); } createArms() { return new ArmsZombieIntact(); } createShirt() { return new ShirtZombieClean(); } createShoes() { return new ShoesZombieNew(); } createType() { return new TypeZombieCrawler(); } } // FACTORY function appZombieRenderFactory(factory){ const renderZombie = { head: factory.createHead(), arms: factory.createArms(), shirt: factory.createShirt(), shoes: factory.createShoes(), type: factory.createType(), } return renderZombie } // POSIBILITY_ZOMBIES function renderZombie(type) { const zombiesList = { runnerWornOut : ZombieRunnerWornOut , walkerNew : ZombieWalkerNew , crawlerTattered : ZombieCrawlerTattered , runnerIntact : ZombieRunnerIntact , walkerDestroyed : ZombieWalkerDestroyed , crawlerNew : ZombieCrawlerNew , runnerBloody : ZombieRunnerBloody , walkerPartial : ZombieWalkerPartial , crawlerOld : ZombieCrawlerOld , runnerTattered : ZombieRunnerTattered , walkerBloody : ZombieWalkerBloody , crawlerBroken : ZombieCrawlerBroken , runnerClean : ZombieRunnerClean , walkerMissing : ZombieWalkerMissing , crawlerIntact : ZombieCrawlerIntact , } const Zombie = zombiesList[type] if (!Zombie) { throw new Error(`This zombie '${type}' is not recognized`); } return new Zombie() } console.log(appZombieRenderFactory(renderZombie('runnerWornOut'))) console.log(appZombieRenderFactory(renderZombie('walkerPartial'))) console.log(appZombieRenderFactory(renderZombie('walkerMissing'))) console.log(appZombieRenderFactory(renderZombie('crawlerTattered'))) ```
Les dejo mi c贸digo en Typescript por si algui茅n le interesa y quiera pasarle diferentes valores a la cpu y memory: ```js interface CPU { setSeries(series: string): void; } interface Memory { setCapacityInGB(gb: number): void; } interface Display { setResolution(): void; } interface AbstractFactoryDevice { createCPU(): CPU; createMemory(): Memory; createDisplay(): Display; } /* CPU */ class PhoneCPU implements CPU { setSeries(series: string): void { console.log(`Phone ${series}`); } } class LaptopCPU implements CPU { setSeries(series: string): void { console.log(`Laptop ${series}`); } } class TabletCPU implements CPU { setSeries(series: string): void { console.log(`Tablet ${series}`); } } /* Memory */ class PhoneMemory implements Memory { setCapacityInGB(gb: number): void { console.log(`Phone ${gb} gb`); } } class LaptopMemory implements Memory { setCapacityInGB(gb: number): void { console.log(`Laptop ${gb} gb`); } } class TabletMemory implements Memory { setCapacityInGB(gb: number): void { console.log(`Tablet ${gb} gb`); } } /* Display */ class PhoneDisplay implements Display { setResolution(): void { console.log(`Phone resolution`); } } class LaptopDisplay implements Display { setResolution(): void { console.log(`Laptop resolution`); } } class TabletDisplay implements Display { setResolution(): void { console.log(`Tablet resolution`); } } /* Phone */ class PhoneFactory implements AbstractFactoryDevice { createCPU(): CPU { return new PhoneCPU(); } createDisplay(): Display { return new PhoneDisplay(); } createMemory(): Memory { return new PhoneMemory(); } } /* Laptop */ class LaptopFactory implements AbstractFactoryDevice { createCPU(): CPU { return new LaptopCPU(); } createDisplay(): Display { return new LaptopDisplay(); } createMemory(): Memory { return new LaptopMemory(); } } /* Tablet */ class TabletFactory implements AbstractFactoryDevice { createCPU(): CPU { return new TabletCPU(); } createDisplay(): Display { return new TabletDisplay(); } createMemory(): Memory { return new TabletMemory(); } } interface appDeviceFactoryProps { factory: AbstractFactoryDevice; cpuDevice: string; memoryDevice: number; } function appDeviceFactory({ factory, cpuDevice, memoryDevice, }: appDeviceFactoryProps) { const cpu = factory.createCPU(); const memory = factory.createMemory(); const display = factory.createDisplay(); cpu.setSeries(cpuDevice); memory.setCapacityInGB(memoryDevice); display.setResolution(); } type typeDevice = "phone" | "laptop" | "tablet"; function createDeviceFactory(type: typeDevice) { const devices = { phone: PhoneFactory, laptop: LaptopFactory, tablet: TabletFactory, }; const Factory = devices[type]; return new Factory(); } appDeviceFactory({ factory: createDeviceFactory("phone"), cpuDevice: "i7", memoryDevice: 512, }); appDeviceFactory({ factory: createDeviceFactory("laptop"), cpuDevice: "i3", memoryDevice: 1024, }); appDeviceFactory({ factory: createDeviceFactory("tablet"), cpuDevice: "i6", memoryDevice: 920, }); ```
```js /** * 1. Declare base products classes/interfaces for each product * in the catalog. * * Base products: * - CPU * - Memory * - Display * * 2. Implement concrete products classes that inherits/implements * base products classes/interfaces, the number of concrete products * will depend on the number of families. * * Concrete products: * - PhoneCPU * - PhoneMemory * - PhoneDisplay * - LaptopCPU * - LaptopMemory * - LaptopDisplay * - TabletCPU * - TabletMemory * - TabletDisplay * * 3. Declare abstract factory class/interface that declare creation * methods for each base product. The return value could be the base * products types or concrete products types. * * Abstract Factory: * - AccessoryFactory * * createCPUAccessory(): CPU * * createMemoryAccessory(): Memory * * createDisplayAccessory(): Display * * 4. Create concrete factories that implements/inherits from the * abstract factory behavior and implements all the products creation * methods. The number of concrete factories will depend of the number * of product families. * * Concrete Factories: * - PhoneFactory * - LaptopFactory * - TabletFactory * */ // Step 1 interface CPU { setSeries(series: string): void; } interface Memory { setCapacityInGB(capacity: number): void; } interface Display { setResolution(): void; } //Step 2 class PhoneCPU implements CPU { setSeries(series) { console.log(`[CPU] ${series} phone series`); } } class PhoneMemory implements Memory { setCapacityInGB(capacity) { console.log(`[MEMORY] ${capacity} phone capacity in GB`); } } class PhoneDisplay implements Display { setResolution() { console.log(`[DISPLAY] phone resolution`); } } class LaptopCPU implements CPU { setSeries(series) { console.log(`[CPU] ${series} Laptop series`); } } class LaptopMemory implements Memory { setCapacityInGB(capacity) { console.log(`[MEMORY] ${capacity} Laptop capacity in GB`); } } class LaptopDisplay implements Display { setResolution() { console.log(`[DISPLAY] Laptop resolution`); } } class TabletCPU implements CPU { setSeries(series) { console.log(`[CPU] ${series} Tablet series`); } } class TabletMemory implements Memory { setCapacityInGB(capacity) { console.log(`[MEMORY] ${capacity} Tablet capacity in GB`); } } class TabletDisplay implements Display { setResolution() { console.log(`[DISPLAY] Tablet resolution`); } } // Step 3 interface AccessoryFactory { createCPUAccessory(): CPU; createMemoryAccessory(): Memory; createDisplayAccessory(): Display; } // Step 4 class PhoneFactory implements AccessoryFactory { createCPUAccessory(): CPU { return new PhoneCPU(); } createMemoryAccessory(): Memory { return new PhoneMemory(); } createDisplayAccessory(): Display { return new PhoneDisplay(); } } class LaptopFactory implements AccessoryFactory { createCPUAccessory(): CPU { return new LaptopCPU(); } createMemoryAccessory(): Memory { return new LaptopMemory(); } createDisplayAccessory(): Display { return new LaptopDisplay(); } } class TabletFactory implements AccessoryFactory { createCPUAccessory(): CPU { return new TabletCPU(); } createMemoryAccessory(): Memory { return new TabletMemory(); } createDisplayAccessory(): Display { return new TabletDisplay(); } } function appAccessoryFactory(factory: AccessoryFactory) { console.log('--- [TS] Calling appAbstractFactory ---\n'); if (!factory) { console.log('--- No factory provided ---'); return; } const cpu: CPU = factory.createCPUAccessory(); const memory: Memory = factory.createMemoryAccessory(); const display: Display = factory.createDisplayAccessory(); cpu.setSeries('12345'); memory.setCapacityInGB(64); display.setResolution(); } appAccessoryFactory(new PhoneFactory()); appAccessoryFactory(new LaptopFactory()); appAccessoryFactory(new TabletFactory()); ```