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
8 Hrs
29 Min
40 Seg

Factory: pros y contras

11/27
Resources

Why is the Factory pattern relevant in software development?

The Factory pattern is a pillar in software design, especially when looking for a robust and flexible system. It allows the creation of concrete objects but from a common abstraction layer, which offers advantages when building complex applications. This approach reduces the high coupling between the creator elements and the products, that is to say, it maintains the independence of the components, facilitating their reuse and maintenance.

What are the advantages of using the Factory pattern?

  • Decoupling: The independence between the creator elements and the products prevents changes in one from affecting the other, promoting a more stable system.

  • Unified responsibility: Implemented as part of the SOLID principles, the Factory pattern ensures that each method or class performs a specific task. Factories create and return products without side effects.

  • Ease of extension: Adding new products or factories does not require modifying existing ones, only extending them. This supports extensibility, making software design elegant and scalable.

What are the disadvantages of the Factory pattern?

  • Excess generic code: While it is simple to add new products, creating new factories for each product can lead to unnecessarily complex code, especially if handling products in large quantities.

  • Excessive abstractions: Sometimes, it is not necessary to use so many abstractions, and can be solved with more straightforward solutions, which optimizes time and resources. However, in large and complex systems, abstractions are necessary for efficient code management.

When is it ideal to use the Factory pattern?

If not all the necessary products are known in advance.

When new products are expected to appear without an exact initial number, the Factory pattern provides a flexible framework where new additions are easy to integrate. This makes it ideal for projects with fluctuating or constantly growing requirements.

Decoupling product creation and usage

One of the main functionalities of the Factory pattern is to separate the creation logic from the use of products. This allows changes in the implementation of products without affecting the parts of the code that use them, keeping the system decoupled and manageable.

To extend libraries or frameworks

In situations where additional functionality needs to be added to existing libraries without modifying their internal structure, the Factory pattern is extremely useful. It facilitates the integration of new features easily into pre-existing frameworks by implementing shared behaviors.

Practical example: HTTP adapters in NestJS

NestJS is a framework for creating server applications that works seamlessly with Express. However, it also gives the option of using Fastify thanks to the flexibility of the Factory pattern. Both Express and Fastify can be "injected" into NestJS because they implement a similar contract, demonstrating how the Factory pattern allows you to switch between different library options without complications.

Your challenge: Create an HTTP adapter

The challenge is to create your own HTTP adapter for NestJS using a Factory pattern. You must implement common methods such as Get, Post, Put and Delete. The idea is to make sure that the completed structure and methods pave the way for future innovation to perhaps build the next trendy web framework. This activity stimulates a deep understanding of how patterns can be applied in modern and flexible architectures.

Contributions 27

Questions 3

Sort by:

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

No estoy seguro si asi consistia el reto pero ahi va mi solucion

/** STEP 1 */
class HttpAdapter {
    constructor(type) {
        this._type = type;
    }
    get() {
        throw new Error('Methor not implemented')
    }
    post() {
        throw new Error('Methor not implemented')
    }
    put() {
        throw new Error('Methor not implemented')
    }
    delete() {
        throw new Error('Methor not implemented')
    }
    getType() {
        return this._type;
    }
}

class Express extends HttpAdapter {
    constructor() {
        super('Express');
    }
    get() {
        console.log(`get Method for ${this._type} adapter`);
    }
    post() {
        console.log(`post Method for ${this._type} adapter`);
    }
    put() {
        console.log(`put Method for ${this._type} adapter`);
    }
    delete() {
        console.log(`delete Method for ${this._type} adapter`);
    }
}
class NestJs extends HttpAdapter {
    constructor() {
        super('NestJs');
    }
    get() {
        console.log(`get Method for ${this._type} adapter`);
    }
    post() {
        console.log(`post Method for ${this._type} adapter`);
    }
    put() {
        console.log(`put Method for ${this._type} adapter`);
    }
    delete() {
        console.log(`delete Method for ${this._type} adapter`);
    }
}

class HttpAdaptrFactory {
    makeAdapter() {
        throw new Error('Method not implement')
    }
}

class ExpressFactory extends HttpAdaptrFactory {
    makeAdapter() {
        return new Express();
    }
}

class NestJsFactory extends HttpAdaptrFactory {
    makeAdapter() {
        return new NestJs();
    }
}

function appAdapter (adapter) {
    const httpAdapter = adapter.makeAdapter()
    httpAdapter.get();
    httpAdapter.post();
    httpAdapter.put();
    httpAdapter.delete();
    console.log(httpAdapter.getType())
}

function createAdaper(type) {
    const adapters = {
        'express': ExpressFactory,
        'nestjs': NestJsFactory
    }
    
    const Adapters = adapters[type]
    return new Adapters()
}

appAdapter(createAdaper('express'))
appAdapter(createAdaper('nestjs'))

¡Hola! He dejado en mi repositorio en github el código del reto en typescript y en python, les dejo el link por si quieren echar un vistazo.

Aqui mi solución 😄

// STEP 1:
abstract class HttpAdapter {
    public constructor(type: string) {}

    public abstract get(): void;
    public abstract post(): void;
    public abstract put(): void;
    public abstract delete(): void;
}

// STEP 2:
class ExpressHttpAdapter extends HttpAdapter {
    constructor() {
        super("Express");
    }

    get() {
        console.log("Express get method");
    }
    post() {
        console.log("Express post method");
    }
    put() {
        console.log("Express put method");
    }
    delete() {
        console.log("Express delete method");
    }
}

// STEP 3:
interface HttpAdapterFactory {
    makeAdapter(): HttpAdapter;
}

// STEP 4:
class ExpressHttpAdapterFactory implements HttpAdapterFactory {
    makeAdapter(): HttpAdapter {
        return new ExpressHttpAdapter();
    }
}

function clientApp() {
    const expressHttpAdapter = new ExpressHttpAdapter();
    expressHttpAdapter.get();
    expressHttpAdapter.post();
    expressHttpAdapter.put();
    expressHttpAdapter.delete();
}
clientApp();

interface HttpAdapterFactory {
    makeAdapter(): HttpAdapter
}

interface HttpAdapter {
    get(): void
    post(): void
    put(): void
    delete(): void
}

class ExpressAdapter implements HttpAdapter {
    get(): void {
        console.log('Express método get')
    }

    post(): void {
        console.log('Express método post')
    }

    put(): void {
        console.log('Express método put')
    }

    delete(): void {
        console.log('Express método delete')
    }
}

class FastifyAdapter implements HttpAdapter {
    get(): void {
        console.log('Fastify método get')
    }

    post(): void {
        console.log('Fastify método post')
    }

    put(): void {
        console.log('Fastify método put')
    }

    delete(): void {
        console.log('Fastify método delete')
    }
}

class ExpressFactory implements HttpAdapterFactory {
    makeAdapter(): HttpAdapter {
        return new ExpressAdapter()
    }
}

class FastifyFactory implements HttpAdapterFactory {
    makeAdapter(): HttpAdapter {
        return new FastifyAdapter()
    }
}

function appFactory(factory: HttpAdapterFactory): void {
    const adapter = factory.makeAdapter()
    adapter.get()
    adapter.post()
    adapter.delete()
}

function createFactory(type: 'express' | 'fastify'): HttpAdapterFactory {
    const factories = {
        express: ExpressFactory,
        fastify: FastifyFactory
    }

    const Factory = new factories[type]
    return Factory
}

appFactory(createFactory('express'))
appFactory(createFactory('fastify'))

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

// creo la interface para los http adapter
interface IHttpAdapter {
  get(): void;
  post(): void;
  put(): void;
  delete(): void;
  getType(): void;
}

// implemento la interface para las class de http adapters
class RestHttpAdapter implements IHttpAdapter {
  private type: string = "REST";

  get() {
    console.log("Method get in " + this.type);
  }
  post() {
    console.log("Method post in " + this.type);
  }
  put() {
    console.log("Method put in " + this.type);
  }
  delete() {
    console.log("Method delete in " + this.type);
  }
  getType(): void {
    console.log(this.type);
  }
}

class SoapHttpAdapter implements IHttpAdapter {
  private type: string = "SOAP";

  get() {
    console.log("Method get in " + this.type);
  }
  post() {
    console.log("Method post in " + this.type);
  }
  put() {
    console.log("Method put in " + this.type);
  }
  delete() {
    console.log("Method delete in " + this.type);
  }
  getType(): void {
    console.log(this.type);
  }
}

// creo la interface factory
interface IHttpAdapterFactory {
  makeAdapter(): IHttpAdapter;
}

// implemento la interface factory para las class factory
class RestHttpAdapterFactory implements IHttpAdapterFactory {
  makeAdapter(): IHttpAdapter {
    return new RestHttpAdapter();
  }
}

class SoapHttpAdapterFactory implements IHttpAdapterFactory {
  makeAdapter(): IHttpAdapter {
    return new SoapHttpAdapter();
  }
}

// funciones para instanciar factories y http adapters
const appFactory2 = (factory: IHttpAdapterFactory) => {
  const httpAdapter = factory.makeAdapter();
  httpAdapter.getType();
  httpAdapter.get();
  httpAdapter.post();
  httpAdapter.put();
  httpAdapter.delete();
};

type HttpAdapterType = "rest" | "soap";

const createFactory2 = (type: HttpAdapterType) => {
  const factories = { rest: RestHttpAdapterFactory, soap: SoapHttpAdapterFactory };
  const Factory = factories[type];
  return new Factory();
};

appFactory2(createFactory2("rest"));
appFactory2(createFactory2("soap"));

Mi solucion a la actividad

/*
    Creamos nuestra clase principal HTTPAdapter que será la encargada de 
    definir los métodos que se utilizarán en los adapters
*/

class HttpAdapter {
    type = undefined;

    constructor(type) {
        this.type = type;
    }

    getType() {
        throw new Error('Method not implemented');
    }

    get(url) {
        return `${this.type} Method GET: ${url}`;
    }

    post(url) {
        return `${this.type} Method POST: ${url}`;
    }

    put(url) {
        return `${this.type} Method PUT: ${url}`;
    }

    delete(url) {
        return `${this.type} Method DELETE: ${url}`;
    }

}

// Definimos nuestros adapters que heredarán de la clase principal
class ExpressAdapter extends HttpAdapter {
    getType() {
        return this.type;
    }
}

class NestJsAdapter extends HttpAdapter {
    getType() {
        return this.type;
    }
}

// Creamos nuestro factory que será el encargado de crear los adapters

const Adapter = {
    // Definimos los adapters disponibles
    factory : {
        Express : NestJsAdapter,
        NestJs: ExpressAdapter,
    },
    // Creamos un método para registrar los adapters
    register : function(type) {
        const NewAdapter = this.factory[type];

        if(!NewAdapter) {
            return "Adapter not found"
        }

        return new NewAdapter(type);
    }
}

const Express = Adapter.register('Express');
const NestJs = Adapter.register('NestJs');

console.log(Express.get('platzi.com')); //output: Express Method GET: platzi.com
console.log(NestJs.delete()); //output: NestJs Method DELETE: undefined

Comparto mi Ts

abstract class HttpAdapter {

    constructor(private _type: string) {

    }
    abstract get(): void;
    abstract post(): void;
    abstract put(): void;
    abstract delete(): void;

   get type(): string {
        return this._type;
    }
}

// adapters concretos 
class AdapterExpress extends HttpAdapter {

    constructor() {
        super('Express');
    }

    get(): void {
        console.log(`get method for ${this.type} adapter`);
    }
    post(): void {
        console.log(`post method for ${this.type} adapter`);
    }
    put(): void {
        console.log(`put method for ${this.type} adapter`);
    }
    delete(): void {
        console.log(`delete method for ${this.type} adapter`);
    }
};


class AdapterNextJs extends HttpAdapter {

    constructor() {
        super('NestJs');
    }

    get(): void {
        console.log(`get method for ${this.type} adapter`);
    }
    post(): void {
        console.log(`post method for ${this.type} adapter`);
    }
    put(): void {
        console.log(`put method for ${this.type} adapter`);
    }
    delete(): void {
        console.log(`delete method for ${this.type} adapter`);
    }
};

// Interface para la abstracion de la fabrica de adapters
interface HttpAdapterFactory {
    makeAdapter(): HttpAdapter
}

// fabricas concretas para cada adapter
class ExpressAdapterFactory implements HttpAdapterFactory {
    makeAdapter(): HttpAdapter {
        return new AdapterExpress;
    };
};

class NextJsAdapterFactory implements HttpAdapterFactory {
    makeAdapter(): HttpAdapter {
        return new AdapterNextJs;
    };
};

// aplicaciones
type HttpAdapterType = 'express' | 'nextjs';

function createFactory(type: HttpAdapterType): HttpAdapterFactory  {
    const factories = {
        'express': ExpressAdapterFactory,
        'nextjs': NextJsAdapterFactory
    };
    const Factory = new factories[type];

    return Factory;
};

function createAdapter(factory: HttpAdapterFactory) {
    const adapter = factory.makeAdapter()
    adapter.get();
    adapter.post();
    adapter.put();
    adapter.delete()
}

createAdapter(createFactory('express'));
createAdapter(createFactory('nextjs'));
Para ponerle un poquito más de desafío, hice mi reto con Swift. Aquí dejo mi solución para los curiosos: ```js import Foundation protocol HttpAdapter { var name: String { get } init(name: String) func get() func post() func put() func delete() } protocol HttpAdapterFactory { associatedtype Adapter: HttpAdapter func makeAdapter() -> Adapter } struct ExpressAdapter: HttpAdapter { internal let name: String init(name: String) { self.name = name } func get() { print("Getting data") } func post() { print("Posting data") } func put() { print("Putting data") } func delete() { print("Deleting data") } } struct ExpressAdapterFactory: HttpAdapterFactory { func makeAdapter() -> ExpressAdapter { return ExpressAdapter(name: "express") } } func run<F: HttpAdapterFactory>(factory: F) { let adapter = factory.makeAdapter() print("Testing adapter methods for: \(adapter.name)") print("============================================") print("Testing GET...") adapter.get() print("Testing POST...") adapter.post() print("Testing PUT...") adapter.put() print("Testing DELETE...") adapter.delete() print("============================================") } run(factory: ExpressAdapterFactory()) ```
Mi aporte del ejercicio en python: ```js from __future__ import annotations from abc import ABC, abstractmethod class HttpAdapter(ABC): def __init__(self, name: str): self.adapter_name = name @abstractmethod def get(self) -> None: pass @abstractmethod def post(self) -> None: pass @abstractmethod def put(self) -> None: pass @abstractmethod def delete(self) -> None: pass class HttpAdapterFactory(ABC): @staticmethod @abstractmethod def make_adapter() -> HttpAdapter: pass class MyAdapter1(HttpAdapter): def __init__(self, name: str): super().__init__(name) def get(self) -> None: print('get method in MyAdapter1') def post(self) -> None: print('post method in MyAdapter1') def put(self) -> None: print('put method in MyAdapter1') def delete(self) -> None: print('delete method in MyAdapter1') class MyAdapter2(HttpAdapter): def __init__(self, name: str): super().__init__(name) def get(self) -> None: print('get method in MyAdapter2') def post(self) -> None: print('post method in MyAdapter2') def put(self) -> None: print('put method in MyAdapter2') def delete(self) -> None: print('delete method in MyAdapter2') class FabricAdapter1(HttpAdapterFactory): @staticmethod def make_adapter() -> HttpAdapter: return MyAdapter1('MyAdapterX') class FabricAdapter2(HttpAdapterFactory): @staticmethod def make_adapter() -> HttpAdapter: return MyAdapter2('MyAdapterY') if __name__ == "__main__": adapter_creator1 = FabricAdapter1() http_adapter = adapter_creator1.make_adapter() http_adapter.get() http_adapter.post() http_adapter.put() http_adapter.delete() print() adapter_creator2 = FabricAdapter2() http_adapter = adapter_creator2.make_adapter() http_adapter.get() http_adapter.post() http_adapter.put() http_adapter.delete() ```

Ahí humildemente, si tengo algo malo, diganme xd

/**
 * Como implementar factory?
 * 1. Declara una clase/interface de producto base, que será devuelta por la clase de la fábrica y sus subclases.
 * 2. Implementa subclases de productos concretos que hereden/implementen la clase/interface de producto base.
 * 3. Declara una clase/interface de fábrica que devuelva objetos que coincidan con el producto base, no con los productos concretos.
 * 4. Implementa subclases de fábricas concretas que hereden/implementen la clase/interface de fábrica base. Estas clases devolverán productos
 * concretos en su método de fábrica.
 */

/** Paso 1 */
class HttpAdapter {

    constructor(type){
        this.type = type;
    }

    get() {
        throw new Error('Method not implemented!');
    }

    post() {
        throw new Error('Method not implemented!');
    }

    put() {
        throw new Error('Method not implemented!');
    }

    delete() {
        throw new Error('Method not implemented!');
    }
}

/** Paso 2 */
class ExpressHttpAdapter extends HttpAdapter {

    constructor() {
        super('express');
    }

    get() {
        console.log('Get desde Express');
    }

    post() {
        console.log('Post desde Express');
    }

    put() {
        console.log('Put desde Express');
    }

    delete() {
        console.log('Delete desde Express');
    }
}

class FastifyHttpAdapter extends HttpAdapter {
    constructor() {
        super('fastify');
    }

    get() {
        console.log('Get desde Fastify');
    }

    post() {
        console.log('Post desde Fastify');
    }

    put() {
        console.log('Put desde Fastify');
    }

    delete() {
        console.log('Delete desde Fastify');
    }
}

/** Paso 3 */
class HttpAdapterFactory {
    makeAdapter() {
        throw new Error('Method not implemented!');
    }
}

/** Paso 4 */
class ExpressHttpAdapterFactory extends HttpAdapterFactory {
    makeAdapter() {
        return new ExpressHttpAdapter('express');
    }
}

class FastifyHttpAdapterFactory extends HttpAdapterFactory {
    makeAdapter() {
        return new FastifyHttpAdapter('fastify');
    }
}

/* Client App */

function clienteApp(factory) {
    const adapter = factory.makeAdapter();
    adapter.get();
    console.log(adapter.type);
}

clienteApp(new ExpressHttpAdapterFactory());
clienteApp(new FastifyHttpAdapterFactory());
Hola! Aquí dejo mi solución, espero les agrade. ```ts abstract class HttpAdapter { constructor(protected readonly name: string) { } get(): void { console.log(`${this.name}:: get()`) } post(): void { console.log(`${this.name}:: post()`) } put(): void { console.log(`${this.name}:: put()`) } delete(): void { console.log(`${this.name}:: delete()`) } } class ExpressHttpAdapter extends HttpAdapter { get() { console.log(`${this.name}:: expressGET()`) } } class PureHttpAdapter extends HttpAdapter { post() { console.log(`${this.name}:: fastifyPOST()`) } } class FastifyHttpAdapter extends HttpAdapter { constructor(name: string, private readonly alias: string) { super(name) } delete() { console.log(`${this.name}-(${this.alias}):: fastifyDELETE()`) } } // ......... interface HttpAdapterFactory { makeAdapter(): HttpAdapter } class ExpressHttpAdapterFactory implements HttpAdapterFactory { makeAdapter(): HttpAdapter { return new ExpressHttpAdapter('ExpressAdapter'); } } class PureHttpAdapterFactory implements HttpAdapterFactory { makeAdapter(): HttpAdapter { return new PureHttpAdapter('PureAdapter'); } } class FastifyHttpAdapterFactory implements HttpAdapterFactory { makeAdapter(): HttpAdapter { return new FastifyHttpAdapter('FastifyAdapter', 'fasti'); } } // --------------------- function clientApp(factory: HttpAdapterFactory) { const httpAdapter = factory.makeAdapter(); httpAdapter.get(); httpAdapter.post(); httpAdapter.delete(); } // clientApp(new ExpressHttpAdapterFactory()) // clientApp(new PureHttpAdapterFactory()) // clientApp(new FastifyHttpAdapterFactory()) type TypeHttpAdapterfactory = 'express' | 'pure' | 'fastify'; const httpAdapterFactories: Record<TypeHttpAdapterfactory, new () => HttpAdapterFactory> = { 'express': ExpressHttpAdapterFactory, 'pure': PureHttpAdapterFactory, 'fastify': FastifyHttpAdapterFactory } function createHttpAdapter(type: TypeHttpAdapterfactory) { const FactoryClass = httpAdapterFactories[type]; return new FactoryClass(); } clientApp(createHttpAdapter("express")) clientApp(createHttpAdapter("fastify")) clientApp(createHttpAdapter("pure")) ```
```ts /** Step 1 */ interface HttpAdapter { get(): void; post(): void; put(): void; delete(): void; } interface HttpAdapterFactory { createAdapter(): HttpAdapter; } /** Step 2 */ class ExpressAdapter implements HttpAdapter { constructor(string: string) { console.log('ExpressAdapter constructor'); } get() { console.log('ExpressAdapter get'); } post() { console.log('ExpressAdapter post'); } put() { console.log('ExpressAdapter put'); } delete() { console.log('ExpressAdapter delete'); } } class FastifyAdapter implements HttpAdapter { constructor(string: string) { console.log('FastifyAdapter constructor'); } get() { console.log('FastifyAdapter get'); } post() { console.log('FastifyAdapter post'); } put() { console.log('FastifyAdapter put'); } delete() { console.log('FastifyAdapter delete'); } } /** Step 3 */ class ExpressAdapterFactory implements HttpAdapterFactory { createAdapter(): HttpAdapter { return new ExpressAdapter('ExpressAdapter'); } } class FastifyAdapterFactory implements HttpAdapterFactory { createAdapter(): HttpAdapter { return new FastifyAdapter('FastifyAdapter'); } } /** Step 4 */ function clientApp(factory: HttpAdapterFactory) { const adapter = factory.createAdapter(); adapter.get(); adapter.post(); adapter.put(); adapter.delete(); } type AdapterType = 'express' | 'fastify'; function clientCreateAdapter(type: AdapterType): HttpAdapterFactory { let factory: HttpAdapterFactory; switch (type) { case 'express': factory = new ExpressAdapterFactory(); break; case 'fastify': factory = new FastifyAdapterFactory(); break; default: throw new Error('Invalid type'); } return factory; } clientApp(clientCreateAdapter('express')); clientApp(clientCreateAdapter('fastify')); ```
Aquí esta mi aporte. Según lo entendido en cada una de las clases previamente vistas. ```js // 1. Creacion del contrato o interfaz para los productos, en JS clase abstracta pura. class HttpAdapter { get() { throw new Error('Method not implemented.') } post() { throw new Error('Method not implemented.') } put() { throw new Error('Method not implemented.') } delete() { throw new Error('Method not implemented.') } } // 2. Cracion de las sub clases que implementan la interfaz o el contrato. class ExpressAdapter extends HttpAdapter { get() { console.log('Quiere hacer una peticion GET a express') } post() { console.log('Quiere hacer una peticion POST a express') } put() { console.log('Quiere hacer una peticion PUT a express') } delete() { console.log('Quiere hacer una peticion DELETE a express') } } class FastifyAdapter extends HttpAdapter { get() { console.log('Quiere hacer una peticion GET a fastify') } post() { console.log('Quiere hacer una peticion POST a fastify') } put() { console.log('Quiere hacer una peticion PUT a fastify') } delete() { console.log('Quiere hacer una peticion DELETE a fastify') } } // 3. Creacion del contrato o interfaz para la factory que generara los productos. class FactoryHttpAdapter { createHttpAdapter() { throw new Error('Method not implemented.') } } // 4. Creacion de la factory que generara los productos implementando la interfaz o el contrato. class FactoryHttpAdapterExpress extends FactoryHttpAdapter { createHttpAdapter() { return new ExpressAdapter() } } class FactoryHttpAdapterFastify extends FactoryHttpAdapter { createHttpAdapter() { return new FastifyAdapter() } } function appHttpAdapter(factory) { if (!factory) { console.log('--- No factory provided ---') return } const httpAdapter = factory.createHttpAdapter() return httpAdapter.get() } function createHttpAdapter(type) { const listOfFactories = { express: FactoryHttpAdapterExpress, fastify: FactoryHttpAdapterFastify } const HttpAdapter = listOfFactories[type] if (!HttpAdapter) { console.log(`Type ${type} not found`) return } return new HttpAdapter() } appHttpAdapter(createHttpAdapter('express')) ```// 1. Creacion del contrato o interfaz para los productos, en JS clase abstracta pura. class HttpAdapter {  get() {    throw new Error('Method not implemented.')  }  post() {    throw new Error('Method not implemented.')  }  put() {    throw new Error('Method not implemented.')  }  delete() {    throw new Error('Method not implemented.')  }} // 2. Cracion de las sub clases que implementan la interfaz o el contrato. class ExpressAdapter extends HttpAdapter {  get() {    console.log('Quiere hacer una peticion GET a express')  }  post() {    console.log('Quiere hacer una peticion POST a express')  }  put() {    console.log('Quiere hacer una peticion PUT a express')  }  delete() {    console.log('Quiere hacer una peticion DELETE a express')  }} class FastifyAdapter extends HttpAdapter {  get() {    console.log('Quiere hacer una peticion GET a fastify')  }  post() {    console.log('Quiere hacer una peticion POST a fastify')  }  put() {    console.log('Quiere hacer una peticion PUT a fastify')  }  delete() {    console.log('Quiere hacer una peticion DELETE a fastify')  }} // 3. Creacion del contrato o interfaz para la factory que generara los productos.class FactoryHttpAdapter {  createHttpAdapter() {    throw new Error('Method not implemented.')  }} // 4. Creacion de la factory que generara los productos implementando la interfaz o el contrato.class FactoryHttpAdapterExpress extends FactoryHttpAdapter {  createHttpAdapter() {    return new ExpressAdapter()  }} class FactoryHttpAdapterFastify extends FactoryHttpAdapter {  createHttpAdapter() {    return new FastifyAdapter()  }} function appHttpAdapter(factory) {  if (!factory) {    console.log('--- No factory provided ---')    return  }  const httpAdapter = factory.createHttpAdapter()  return httpAdapter.get()} function createHttpAdapter(type) {  const listOfFactories = {    express: FactoryHttpAdapterExpress,    fastify: FactoryHttpAdapterFastify  }   const HttpAdapter = listOfFactories\[type]   if (!HttpAdapter) {    console.log(`Type ${type} not found`)    return  }   return new HttpAdapter()} appHttpAdapter(createHttpAdapter('express'))
mi solución :class httpAdapter { name; constructor(adatorName) { this.name = adatorName; } get() { throw new Error("Methor not implemented"); } post() { throw new Error("Methor not implemented"); } put() { throw new Error("Methor not implemented"); } delete() { throw new Error("Methor not implemented"); }} //paso 2class axiosAdapter extends httpAdapter { constructor(adatorName) { super(adatorName); } get() { console.log("axios get"); } post() { console.log("axios post"); } put() { console.log("axios put"); } delete() { console.log("axios delete"); } showName() { console.log(this.name); }} class httpAdapterFactory { createAdapter() { throw new Error("Method not implemented"); }} class concreteAdapterFactory extends httpAdapterFactory { createAdapter(type) { return new axiosAdapter(type); }} function clientApp() { const axiosAdater = new concreteAdapterFactory().createAdapter("joselin"); axiosAdater.get(); axiosAdater.post(); axiosAdater.put(); axiosAdater.delete(); axiosAdater.showName();}clientApp(); ```js class httpAdapter { name; constructor(adatorName) { this.name = adatorName; } get() { throw new Error("Methor not implemented"); } post() { throw new Error("Methor not implemented"); } put() { throw new Error("Methor not implemented"); } delete() { throw new Error("Methor not implemented"); } } //paso 2 class axiosAdapter extends httpAdapter { constructor(adatorName) { super(adatorName); } get() { console.log("axios get"); } post() { console.log("axios post"); } put() { console.log("axios put"); } delete() { console.log("axios delete"); } showName() { console.log(this.name); } } class httpAdapterFactory { createAdapter() { throw new Error("Method not implemented"); } } class concreteAdapterFactory extends httpAdapterFactory { createAdapter(type) { return new axiosAdapter(type); } } function clientApp() { const axiosAdater = new concreteAdapterFactory().createAdapter("joselin"); axiosAdater.get(); axiosAdater.post(); axiosAdater.put(); axiosAdater.delete(); axiosAdater.showName(); } clientApp(); ```
No sé bien si debía hacerse así, pero sí pude crear la clase específica y hacer referencia a los métodos de la clase base:```js class HttpAdapter { Get() { throw new Error('This method is not implemented'); } Post() { throw new Error('This method is not implemented'); } Put() { throw new Error('This method is not implemented'); } Delete() { throw new Error('This method is not implemented'); } } // Derived class implementing HTTP Adapter methods class HttpAdapterMST extends HttpAdapter { Get() { console.log('Este es el método Get'); } Post() { console.log('Este es el método Post'); } Put() { console.log('Este es el método Put'); } Delete() { console.log('Este es el método Delete'); } } // Base class for the Factory class HttpAdapterFactory { MakeAdapter() { throw new Error('This method is not implemented'); } } // Factory class for creating MST Adapter instances class MSTAdapterFactory extends HttpAdapterFactory { MakeAdapter() { return new HttpAdapterMST(); } } // Function that uses the factory to create and test the adapter function appFactory(factory) { const adaptador = factory.MakeAdapter(); adaptador.Get(); adaptador.Post(); adaptador.Put(); adaptador.Delete(); } // Correctly pass the factory instance appFactory(new MSTAdapterFactory()); ```
Mi implementacion del challenge de Facotory: ```js class HttpAdapter { constructor(type) { this.name = type; } get() { throw error("Method not implement."); } post() { throw error("Method not implement."); } put() { throw error("Mehotd not implement."); } delete() { throw error("Method not implement."); } } class HttpAdapterFactory { makeAdapter() { throw error("Method not implement."); } } class Express extends HttpAdapter { constructor() { super("Express") } get() { console.log(`get Method for ${this.name}`); } post() { console.log(`post Method for ${this.name}`); } put() { console.log(`put Method for ${this.name}`); } delete() { console.log(`delete Method for ${this.name}`); } } class ExpressFactory extends HttpAdapterFactory { makeAdapter() { return new Express(); } } class Fastify extends HttpAdapter { constructor() { super("Express") } get() { console.log(`get Method for ${this.name}`); } post() { console.log(`post Method for ${this.name}`); } put() { console.log(`put Method for ${this.name}`); } delete() { console.log(`delete Method for ${this.name}`); } } class FastifyFactory extends HttpAdapter { makeAdapter() { return new Fastify(); } } function appFactory(factory) { const car = factory.makeCar(); car.showCost(); } appFactory(new ExpressFactory()); appFactory(new FastifyFactory()); ```
```ts // Interfaces interface HttpAdapterInterface { get(): void; post(): void; put(): void; delete(): void; } interface HttpAdapterFactoryInterface { makeAdapter(type: AdapterServicesType): HttpAdapterInterface; } // types type AdapterServicesType = "Express" | "Fastify"; // express adapter class ExpressAdapter implements HttpAdapterInterface { public get(): void { console.log("Método get Express"); } public post(): void { console.log("Método post Express"); } public put(): void { console.log("Método put Express"); } public delete(): void { console.log("Método delete Express"); } } // fastify adapter class FastifyAdapter implements HttpAdapterInterface { public get(): void { console.log("Método get Fastify"); } public post(): void { console.log("Método post Fastify"); } public put(): void { console.log("Método put Fastify"); } public delete(): void { console.log("Método delete Fastify"); } } // Http Adapter (factory) class HttpAdapterFactory implements HttpAdapterFactoryInterface { makeAdapter(type: AdapterServicesType): HttpAdapterInterface { switch (type) { case "Express": return new ExpressAdapter(); case "Fastify": return new FastifyAdapter(); default: throw new Error(`Adapter type "${type}" no es válido...`); } } } // example const factory = new HttpAdapterFactory(); // test Express const express_service: ExpressAdapter = factory.makeAdapter("Express"); express_service.get(); express_service.post(); // test Fastify const fastify_services: FastifyAdapter = factory.makeAdapter("Fastify"); fastify_services.put(); fastify_services.delete(); ```
El patron factory es muy conveniente para la implementacion de pasarelas de pago, ya que si el cliente cambia el contrato con otra paserela, el cambio no será tan brusco.
```js class baseCar{ showCosts(){ throw new Error('method not implemented'); } } class ElectricCar extends baseCar{ showCosts(){ console.log('Costos de un coche eléctrico 150,000 us'); } } class HybridCar extends baseCar{ showCosts(){ console.log('Costos de un coche híbrido 30,000 us'); } } class Car extends baseCar{ showCosts(){ console.log('Costos de un coche convencional 25,000 us'); } } class factoryCar { makeCar(){ throw new Error('method not implemented'); } } class ElectricCarFactory extends factoryCar{ makeCar(){ return new ElectricCar(); } } class HybridCarFactory extends factoryCar{ makeCar(){ return new HybridCar(); } } class SingleCarFactory extends factoryCar{ makeCar(){ return new Car(); } } function appFactory(factory){ const car = factory.makeCar(); car.showCosts(); //... otros métodos y propiedades del coche } //appFactory(new HybridCarFactory()); //appFactory(new ElectricCarFactory()); //appFactory(new SingleCarFactory()); function CreateFactory(type){ const factories = { Electric: ElectricCarFactory, Hybrid: HybridCarFactory, Default: SingleCarFactory }; const Factory = factories[type]; return new Factory(); } appFactory(CreateFactory('Electric')); appFactory(CreateFactory('Hybrid')); appFactory(CreateFactory('Default')); ```class baseCar{    showCosts(){    throw new Error('method not implemented');    }} class ElectricCar extends baseCar{    showCosts(){        console.log('Costos de un coche eléctrico 150,000 us');    }} class HybridCar extends baseCar{    showCosts(){        console.log('Costos de un coche híbrido 30,000 us');    }} class Car extends baseCar{    showCosts(){        console.log('Costos de un coche convencional 25,000 us');    }} class factoryCar {    makeCar(){        throw new Error('method not implemented');    }} class ElectricCarFactory extends factoryCar{    makeCar(){        return new ElectricCar();    }} class HybridCarFactory extends factoryCar{    makeCar(){        return new HybridCar();    }} class SingleCarFactory extends factoryCar{    makeCar(){        return new Car();    }} function appFactory(factory){    const car = factory.makeCar();    car.showCosts();    //... otros métodos y propiedades del coche} //appFactory(new HybridCarFactory());//appFactory(new ElectricCarFactory());//appFactory(new SingleCarFactory()); function CreateFactory(type){    const factories = {        Electric: ElectricCarFactory,        Hybrid: HybridCarFactory,        Default: SingleCarFactory    };     const Factory = factories\[type];     return new Factory();} appFactory(CreateFactory('Electric'));appFactory(CreateFactory('Hybrid'));appFactory(CreateFactory('Default'));
`class baseCar{    showCosts(){    throw new Error('method not implemented');    }}` `class ElectricCar extends baseCar{    showCosts(){        console.log('Costos de un coche eléctrico 150,000 us');    }}` `class HybridCar extends baseCar{    showCosts(){        console.log('Costos de un coche híbrido 30,000 us');    }}` `class Car extends baseCar{    showCosts(){        console.log('Costos de un coche convencional 25,000 us');    }}` `class factoryCar {    makeCar(){        throw new Error('method not implemented');    }}` `class ElectricCarFactory extends factoryCar{    makeCar(){        return new ElectricCar();    }}` `class HybridCarFactory extends factoryCar{    makeCar(){        return new HybridCar();    }}` `class SingleCarFactory extends factoryCar{    makeCar(){        return new Car();    }}` `function appFactory(factory){    const car = factory.makeCar();    car.showCosts();    //... otros métodos y propiedades del coche}` `//appFactory(new HybridCarFactory());//appFactory(new ElectricCarFactory());//appFactory(new SingleCarFactory());` `function CreateFactory(type){    const factories = {        Electric: ElectricCarFactory,        Hybrid: HybridCarFactory,        Default: SingleCarFactory    };` `    const Factory = factories[type];` `    return new Factory();}` `appFactory(CreateFactory('Electric'));appFactory(CreateFactory('Hybrid'));appFactory(CreateFactory('Default'));`
```js interface HttpAdapter { get(): void post(): void put(): void delete(): void } class ExpressAdapter implements HttpAdapter { get(): void { console.log('get data') } post(): void { console.log('post data') } put(): void { console.log('put data') } delete(): void { console.log('delete data') } } class FastifyAdapter implements HttpAdapter { get(): void { console.log('get data') } post(): void { console.log('post data') } put(): void { console.log('put data') } delete(): void { console.log('delete data') } } interface HttpAdapterFactory { makeAdapter(): HttpAdapter } class ExpressFactory implements HttpAdapterFactory { makeAdapter(): HttpAdapter { return new ExpressAdapter() } } class FastifyFactory implements HttpAdapterFactory { makeAdapter(): HttpAdapter { return new FastifyAdapter() } } function httpAdapterFactory(factory: HttpAdapterFactory) { const httpAdapter: HttpAdapter = factory.makeAdapter() httpAdapter.get() httpAdapter.post() httpAdapter.put() httpAdapter.delete() } type FactoryType = 'express' | 'fastify' function createFactory(type: FactoryType) { const factories = { express: ExpressFactory, fastify: FastifyFactory, } const Factory = factories[type] return new Factory() } httpAdapterFactory(createFactory('express')) httpAdapterFactory(createFactory('fastify')) ```*interface* <u>HttpAdapter</u> {  get(): *void*  post(): *void*  put(): *void*  delete(): *void*} *class* <u>ExpressAdapter</u> implements *<u>HttpAdapter</u>* {  get(): *void* {    console.log('get data')  }   post(): *void* {    console.log('post data')  }   put(): *void* {    console.log('put data')  }   delete(): *void* {    console.log('delete data')  }} *class* <u>FastifyAdapter</u> implements *<u>HttpAdapter</u>* {  get(): *void* {    console.log('get data')  }   post(): *void* {    console.log('post data')  }   put(): *void* {    console.log('put data')  }   delete(): *void* {    console.log('delete data')  }} *interface* <u>HttpAdapterFactory</u> {  makeAdapter(): <u>HttpAdapter</u>} *class* <u>ExpressFactory</u> implements *<u>HttpAdapterFactory</u>* {  makeAdapter(): <u>HttpAdapter</u> {      return new ExpressAdapter()  }} *class* <u>FastifyFactory</u> implements *<u>HttpAdapterFactory</u>* {  makeAdapter(): <u>HttpAdapter</u> {      return new FastifyAdapter()  }} *function* httpAdapterFactory(*factory*: <u>HttpAdapterFactory</u>) {  *const* httpAdapter: <u>HttpAdapter</u> = factory.makeAdapter()  httpAdapter.get()  httpAdapter.post()  httpAdapter.put()  httpAdapter.delete() } *type* <u>FactoryType</u> = 'express' | 'fastify' *function* createFactory(*type*: <u>FactoryType</u>) {  *const* factories = {    express: ExpressFactory,    fastify: FastifyFactory,  }   *const* Factory = factories\[type]   return new Factory()} httpAdapterFactory(createFactory('express'))httpAdapterFactory(createFactory('fastify'))
`class HttpAdapter {` ` constructor(type){` ` this._type= type` ` }` ` get(){` ` throw new Error ("metodo no impplementado")` ` }` ` post(){` ` throw new Error ("metodo no impplementado")` ` }` ` put(){` ` throw new Error ("metodo no impplementado")` ` }` ` delet(){` ` throw new Error ("metodo no impplementado")` ` }` `}` `class Express extends HttpAdapter{` ` constructor(){` ` super("Express")` ` }` ` ` ` get(){` ` console.log("metodo no impplementadssssssssso")` ` }` ` post(){` ` console.log("Express post")` ` }` ` put(){` ` console.log("Express put")` ` }` ` delet(){` ` console.log("Express delet")` ` }` `}` `class NestJss extends HttpAdapter{` ` constructor(){` ` super("nestJs")` ` }` ` ` ` get(){` ` console.log("NestJss get")` ` }` ` post(){` ` console.log("NestJss post")` ` }` ` put(){` ` console.log("NestJss put")` ` }` ` delet(){` ` console.log("NestJss delet")` ` }` `}` `class HttpAdaptrFactory {` ` makeAdaoter(){` ` throw new Error ("metodo no impplementado")` ` }` `}` `class HttpAdapterExpress extends HttpAdaptrFactory{` ` makeAdapter(){` ` return new Express();` ` }` `}` `class HttpAdapterNest extends HttpAdaptrFactory{` ` makeAdapter(){` ` return new NestJss();` ` }` `}` `function HttpAdapterFactory(adapter) {` ` const httpAdapter = adapter.makeAdapter()` ` httpAdapter.get();` ` httpAdapter.post();` ` httpAdapter.put();` ` httpAdapter.delet();` ` ` `}` `function createHttpAdapter(type){` ` const adapter = {` ` nestJs:HttpAdapterNest,` ` express:HttpAdapterExpress` ` }` ` const Adapter = adapter[type]` ` return new Adapter()` `}` `HttpAdapterFactory(createHttpAdapter('express'))`
Aca dejo mi propuesta: ```js /* Base Class */ abstract class HttpAdapter { constructor(adapterType: string){} get(){ throw new Error("Method not implemented") } post(){ throw new Error("Method not implemented") } put(){ throw new Error("Method not implemented") } delete(){ throw new Error("Method not implemented") } } /* Concrete Classes */ class JestAdapter extends HttpAdapter { get(){ console.log("get method of Jest"); } post(){ console.log("post method of Jest"); } put(){ console.log("put method of Jest"); } delete(){ console.log("delete method of Jest"); } } class NextJSAdapter extends HttpAdapter { get(){ console.log("get method of NextJS"); } post(){ console.log("post method of NextJS"); } put(){ console.log("put method of NextJS"); } delete(){ console.log("delete method of NextJS"); } } /* Base Factory */ abstract class HttpAdapterFactory { abstract makeAdapter ():HttpAdapter; } /* Concrete Factories */ class JestAdapterFactory extends HttpAdapterFactory { makeAdapter ():HttpAdapter { return new JestAdapter("Jest"); } } class NextJSAdapterFactory extends HttpAdapterFactory { makeAdapter ():HttpAdapter { return new NextJSAdapter("NextJS"); } } // Testing function generateAdapter (type: "Jest" | "NextJS") { const adapters = { "Jest": JestAdapterFactory, "NextJS": NextJSAdapterFactory, }; const Adapter = adapters[type]; return new Adapter(); } function callAdapter (adapter: HttpAdapterFactory) { const httpAdapter = adapter.makeAdapter(); httpAdapter.get(); httpAdapter.post(); httpAdapter.put(); httpAdapter.delete(); } callAdapter(generateAdapter("Jest")); callAdapter(generateAdapter("NextJS")); ```/\* Base Class \*/ abstract class HttpAdapter {    constructor(adapterType: string){}     get(){ throw new Error("Method not implemented") }    post(){ throw new Error("Method not implemented") }    put(){ throw new Error("Method not implemented") }    delete(){ throw new Error("Method not implemented") }} /\* Concrete Classes \*/ class JestAdapter extends HttpAdapter {     get(){ console.log("get method of Jest"); }    post(){ console.log("post method of Jest"); }    put(){ console.log("put method of Jest"); }    delete(){ console.log("delete method of Jest"); }} class NextJSAdapter extends HttpAdapter {     get(){ console.log("get method of NextJS"); }    post(){ console.log("post method of NextJS"); }    put(){ console.log("put method of NextJS"); }    delete(){ console.log("delete method of NextJS"); }} /\* Base Factory \*/ abstract class HttpAdapterFactory {    abstract makeAdapter ():HttpAdapter;} /\* Concrete Factories \*/ class JestAdapterFactory extends HttpAdapterFactory {    makeAdapter ():HttpAdapter  {        return new JestAdapter("Jest");    }} class NextJSAdapterFactory extends HttpAdapterFactory {    makeAdapter ():HttpAdapter  {        return new NextJSAdapter("NextJS");    }} // Testingfunction generateAdapter (type: "Jest" | "NextJS") {    const adapters = {        "Jest": JestAdapterFactory,        "NextJS": NextJSAdapterFactory,    };     const Adapter = adapters\[type];     return new Adapter();    } function callAdapter (adapter: HttpAdapterFactory) {    const httpAdapter = adapter.makeAdapter();    httpAdapter.get();    httpAdapter.post();    httpAdapter.put();    httpAdapter.delete();} callAdapter(generateAdapter("Jest"));callAdapter(generateAdapter("NextJS"));
Escogí un reto diferente \------------------------------- PROBLEMA Reto: Sistema de Notificación Contexto Supongamos que estás desarrollando un sistema en el que necesitas enviar notificaciones a los usuarios. Estas notificaciones pueden ser de diferentes tipos: por email, SMS, y notificaciones push en una aplicación móvil. Cada tipo de notificación tiene su propia forma de ser enviada, pero desde el punto de vista del sistema, simplemente necesitas una manera de enviar la notificación, sin preocuparte por los detalles específicos de cada tipo. Objetivo Implementar un sistema de notificaciones utilizando el patrón Factory. Requisitos Interfaz Común de Notificación: Crea una interfaz Notificacion que tenga un método enviar(mensaje). Implementaciones Concretas: Crea tres clases concretas que implementen Notificacion: NotificacionEmail para enviar notificaciones por email. NotificacionSMS para enviar notificaciones por SMS. NotificacionPush para enviar notificaciones push a una aplicación móvil. Fábrica de Notificaciones: Crea una clase FabricaNotificaciones que tenga un método estático crearNotificacion(tipo) que devuelva una instancia del tipo de notificación deseado. Pruebas: Escribe un código que utilice FabricaNotificaciones para crear diferentes tipos de notificaciones y enviar un mensaje. Consideraciones Adicionales Piensa en cómo podrías expandir este sistema en el futuro para incluir nuevos tipos de notificaciones sin modificar la fábrica existente. No es necesario implementar la lógica real de envío de notificaciones; puedes usar impresiones en consola para simular las acciones. \------------------------------- CODIGO \------------------------------ ```js class Notification { sendMessage(message) { throw new Error('This method not implemented') } } class NotificationEMAIL extends Notification { sendMessage(message){ return `Notifications via email : ${message}` } } class NotificacionSMS extends Notification { sendMessage(message){ return `Notifications sms : ${message}` } } class NotificationPUSH extends Notification { sendMessage(message){ return `Notifications push : ${message}` } } function factoryNotifications(type) { const notifications = { sms: NotificacionSMS, push: NotificationPUSH, email: NotificationEMAIL } const NotificationType = notifications[type] if (!NotificationType) { throw new Error(`Notification type '${type}' is not recognized`); } return new NotificationType() } let notificationUser = factoryNotifications('sms') console.log(notificationUser.sendMessage('First Notification')) notificationUser = factoryNotifications('email') console.log(notificationUser.sendMessage('New message via email')) ```
```ts /** * * Factory Method challenge: * * Make a HttpAdapters factory. * * Steps followed to implement the solution: * * 1. Add HttpAdapter base product class * 2. Add concrete implementation of HttpAdapter: RestHttpAdapter * 3. Add HttpAdapterFactory base factory class * 4. Add concrete implementation of HttpAdapterFactory: RestHttpAdapterFactory */ // ----- HttpAdapter base class ----- interface HttpAdapter { get(): void; post(): void; put(): void; delete(): void; } // ----- Concrete product ----- class RestHttpAdapter implements HttpAdapter { get() { console.log('[GET]'); } post() { console.log('[POST]'); } put() { console.log('[PUT]'); } delete() { console.log('[DELETE]'); } } // ----- Base Factory ----- interface HttpAdapterFactory { makeHttpAdapter(): HttpAdapter; } // ----- Concrete Factory ----- class RestHttpAdapterFactory implements HttpAdapterFactory { makeHttpAdapter() { return new RestHttpAdapter(); } } /** * Main function * @param {HttpAdapterFactory} factory HttpAdapter factory */ function appFactory(factory: HttpAdapterFactory) { console.log('--- [TS] Calling appFactory ---\n'); if (!factory) { console.log('--- No factory provided ---'); return; } const adapter: HttpAdapter = factory.makeHttpAdapter(); adapter.get(); adapter.post(); adapter.put(); adapter.delete(); } appFactory(new RestHttpAdapterFactory()); ```

Solución 😄…

.
.
.
.

interface HttpAdapterFactory {
  makeAdapter(): HttpAdapter;
}

class ExpressHttpAdapterFactory implements HttpAdapterFactory {
  makeAdapter() {
    return new ExpressHttpAdapter("express");
  }
}

class FastifyHttpAdapterFactory implements HttpAdapterFactory {
  makeAdapter() {
    return new FastifyHttpAdapter("fastify");
  }
}

class NestJsHttpAdapterFactory implements HttpAdapterFactory {
  makeAdapter() {
    return new NestJsHttpAdapter("nest-js");
  }
}

interface HttpAdapter {
  get(): void;
  post(): void;
  put(): void;
  delete(): void;
}

class ExpressHttpAdapter implements HttpAdapter {
  private type: string;

  constructor(type: string) {
    this.type = type;
  }

  get() {
    console.log(`${this.type} get implementation`);
  }
  post() {
    console.log(`${this.type} post implementation`);
  }
  put() {
    console.log(`${this.type} put implementation`);
  }
  delete() {
    console.log(`${this.type} delete implementation`);
  }
}

class FastifyHttpAdapter implements HttpAdapter {
  private type: string;

  constructor(type: string) {
    this.type = type;
  }

  get() {
    console.log(`${this.type} get implementation`);
  }
  post() {
    console.log(`${this.type} post implementation`);
  }
  put() {
    console.log(`${this.type} put implementation`);
  }
  delete() {
    console.log(`${this.type} delete implementation`);
  }
}

class NestJsHttpAdapter implements HttpAdapter {
  private type: string;

  constructor(type: string) {
    this.type = type;
  }

  get() {
    console.log(`${this.type} get implementation`);
  }
  post() {
    console.log(`${this.type} post implementation`);
  }
  put() {
    console.log(`${this.type} put implementation`);
  }
  delete() {
    console.log(`${this.type} delete implementation`);
  }
}

function appHttpAdapaterFactory(factory: HttpAdapterFactory) {
  const adapter: HttpAdapter = factory.makeAdapter();
  adapter.get();
  adapter.post();
  adapter.put();
  adapter.delete();
}

// appHttpAdapaterFactory(new ExpressHttpAdapterFactory());
// appHttpAdapaterFactory(new FastifyHttpAdapterFactory());
// appHttpAdapaterFactory(new NestJsHttpAdapterFactory());

type HttpAdapterFactoryType = "express" | "fastify" | "nest-js";
function createHttpAdapterFactory(type: HttpAdapterFactoryType) {
  const adapters = {
    express: ExpressHttpAdapterFactory,
    fastify: FastifyHttpAdapterFactory,
    "nest-js": NestJsHttpAdapterFactory,
  };
  const factoryClass = adapters[type];
  return new factoryClass();
}

appHttpAdapaterFactory(createHttpAdapterFactory("express"));
appHttpAdapaterFactory(createHttpAdapterFactory("fastify"));
appHttpAdapaterFactory(createHttpAdapterFactory("nest-js"));

Este reto me tuvo muy entretenido y me pareció muy didáctico. Comparto mi código, creando dos Productos Concretos para ejemplificar:

//PRODUCTOS ADAPTERS

class HttpAdapter {
    get(){
        throw new Error("Metodo get no implementado");
    }

    post(){
        throw new Error('Metodo post no implementado');
    }

    put(){
        throw new Error('Metodo put no implementado');
    }

    delete(){
        throw new Error('Metodo delete no implementado');
    }
}


class HttpAdapterHiro extends HttpAdapter{
    get(){
        console.log("Hiro getMethod");
    }

    post(){
        console.log("Hiro postMethod");
    }

    put(){
        console.log('Hiro putMethod');
    }

    delete(){
        console.log('Hiro deleteMethod');
    }
}

class HttpAdapterAurel extends HttpAdapter{
    get(){
        console.log('Aurel getMethod');
    }

    post(){
        console.log('Aurel postMethod');
    }

    put(){
        console.log('Aurel putMethod');
    }

    delete(){
        console.log('Aurel deleteMethod');
    }
}



//Fabricas

class HttpAdapterFactory{
    makeAdapter() {
        throw new Error('Metodo makeAdapter no implementado');
    }
}

class HttpAdapterHiroFactory extends HttpAdapterFactory{
    makeAdapter() {
        return new HttpAdapterHiro();
    }
}

class HttpAdapterAurelFactory extends HttpAdapterFactory{
    makeAdapter() {
        return new HttpAdapterAurel();
    }
}


//IMPLEMENTACIÓN
function createAdapter(factory){
    const connectAdapter = factory.makeAdapter();
    return connectAdapter;
}

function createFactory(adapter){
    const adapters = {
        hiro: HttpAdapterHiroFactory,
        aurel: HttpAdapterAurelFactory,
    };
    const Factory = adapters[adapter];
    return new Factory();
}