es

Guía completa de patrones de comunicación en JavaScript

December 05, 2023

Tags: Tecnologías

javascript

 

Los patrones de comunicación en JavaScript se refieren a enfoques o prácticas comunes para establecer la comunicación entre diferentes partes de una aplicación, ya sea entre componentes, módulos, objetos o sistemas distribuidos. 

 

Estos patrones facilitan la organización del código, la gestión de eventos, la transferencia de datos y la interacción entre diferentes partes de una aplicación. Los patrones de comunicación entre módulos o componentes son fundamentales en el diseño de sistemas de software, ya que determinan cómo interactúan entre sí las distintas partes de una aplicación.

 

Algunos de los patrones de comunicación comunes en JavaScript incluyen:

 

Patrón de Publicador-Suscriptor (Observer)

 

  • Descripción: Este patrón establece una relación de uno a muchos entre objetos, de modo que cuando un objeto cambia su estado, todos los dependientes son notificados y actualizados automáticamente.
  • Uso: Útil cuando un componente debe informar a varios otros componentes sobre cambios de estado sin acoplamiento directo.

 

Patrón de Invocación Remota (Remote Procedure Call - RPC)

 

  • Descripción: Permite a un programa ejecutar procedimientos o funciones en otro espacio de memoria de manera transparente como si fueran procedimientos locales.
  • Uso: Se utiliza para la comunicación entre procesos distribuidos o componentes de un sistema distribuido.

 

Patrón de Cola de Mensajes (Message Queue)

 

  • Descripción: Los componentes se comunican enviándose mensajes a través de una cola compartida. Cada mensaje contiene información sobre la tarea a realizar y los datos necesarios.
  • Uso: Útil en sistemas distribuidos o microservicios para desacoplar componentes y mejorar la escalabilidad.

 

Patrón de Paso de Mensajes (Message Passing)

 

  • Descripción: Los componentes se comunican enviándose mensajes directamente entre ellos. Puede ser síncrono o asíncrono.
  • Uso: Adecuado cuando se necesita una comunicación directa y específica entre componentes.

 

Patrón de Middleware

 

  • Descripción: Introduce una capa intermedia (middleware) que facilita la comunicación entre diferentes componentes sin que estos estén directamente acoplados.
  • Uso: Se utiliza para simplificar la integración de sistemas heterogéneos.

 

Patrón de Inyección de Dependencias (Dependency Injection)

 

  • Descripción: Permite que un componente reciba sus dependencias de manera externa, en lugar de crearlas internamente. Esto facilita la sustitución de componentes y reduce el acoplamiento.
  • Uso: Mejora la modularidad y facilita las pruebas unitarias.

 

Patrón de Puente (Bridge)

 

  • Descripción: Divide una abstracción de su implementación para que ambas puedan variar independientemente. Se utiliza para desacoplar una abstracción de su implementación, permitiendo que ambas evolucionen por separado.
  • Uso: Útil cuando se desea evitar un vínculo permanente entre una abstracción y su implementación.

 

javascript

 

Frameworks y patrones comúnmente utilizados

 

Patrón de Publicador-Suscriptor (Observer)

 

En Angular, el patrón de Publicador-Suscriptor (Observer) se utiliza en varios lugares, y uno de los ejemplos más notables es en el sistema de manejo de eventos mediante el uso de servicios y el patrón de diseño de Observables. Angular utiliza RxJS (Reactive Extensions for JavaScript) para implementar el patrón Observer. Si se desea comunicar cambios desde un componente A a otro componente B. Se puede utilizar un servicio como intermediario y emitir eventos desde el componente A que el componente B puede escuchar.

 

Crear un servicio para manejar la comunicación

 

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ComunicacionService {
  private subject = new Subject<any>();

  enviarMensaje(mensaje: any) {
    this.subject.next({ mensaje });
  }

  recibirMensaje() {
    return this.subject.asObservable();
  }
}

 

En el componente emisor

 

import { Component } from '@angular/core';
import { ComunicacionService } from 'ruta-al-servicio';

@Component({
  selector: 'app-componente-a',
  template: `
    <button (click)="enviar()">Enviar Mensaje</button>
  `,
})
export class ComponenteA {
  constructor(private comunicacionService: ComunicacionService) {}

  enviar() {
    this.comunicacionService.enviarMensaje('Hola desde Componente A');
  }
}

 

En el componente receptor

 

import { Component, OnDestroy } from '@angular/core';
import { ComunicacionService } from 'ruta-al-servicio';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-componente-b',
  template: `
    <p>Mensaje recibido: {{ mensajeRecibido }}</p>
  `,
})
export class ComponenteB implements OnDestroy {
  mensajeRecibido: any;
  private subscription: Subscription;

  constructor(private comunicacionService: ComunicacionService) {
    this.subscription = this.comunicacionService.recibirMensaje().subscribe((mensaje) => {
      this.mensajeRecibido = mensaje;
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

 

  • ComunicacionService actúa como el servicio que gestiona la comunicación entre componentes.
  • ComponenteA emite un mensaje cuando se hace clic en un botón.
  • ComponenteB escucha los mensajes utilizando el servicio y actualiza su estado en consecuencia.

 

javascript

 

Patrón de Invocación Remota (Remote Procedure Call - RPC)

 

El patrón de Invocación Remota (Remote Procedure Call - RPC) es una técnica que permite la ejecución de funciones o métodos en un sistema remoto como si fueran locales. En el contexto de JavaScript, existen varias implementaciones y tecnologías que permiten realizar llamadas remotas.

 

gRPC con Node.js

 

Pasos básicos para implementar un gRPC con node;

 

1- Define un archivo .proto para describir el servicio:

 

syntax = "proto3";
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

 

2- Compilar archivo .proto

 

Utiliza el compilador de protobuf para generar los archivos JavaScript y TypeScript necesarios:

 

protoc --proto_path=. --js_out=import_style=commonjs,binary:./generated --grpc_out=./generated --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` example.proto

 

Esto generará los archivos example_grpc_pb.js y example_pb.js en el directorio generated.

 

3- Implementar el Servidor gRPC

 

Crea un archivo server.js para implementar el servidor:

 

const grpc = require('grpc');
const { GreeterService } = require('./generated/example_grpc_pb');
const { HelloReply, HelloRequest } = require('./generated/example_pb');

const server = new grpc.Server();

server.addService(GreeterService, {
  sayHello: (call, callback) => {
    const request = call.request;
    const reply = new HelloReply();
    reply.setMessage(`Hello, ${request.getName()}!`);
    callback(null, reply);
  },
});

const PORT = 50051;
server.bind(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure());
console.log(`Server running at http://0.0.0.0:${PORT}`);
server.start();

 

4- Implementar el Cliente gRPC

 

Crea un archivo client.js para implementar el cliente:

 

const grpc = require('grpc');
const { GreeterClient } = require('./generated/example_grpc_pb');
const { HelloRequest } = require('./generated/example_pb');

const client = new GreeterClient('localhost:50051', grpc.credentials.createInsecure());

const request = new HelloRequest();
request.setName('John Doe');

client.sayHello(request, (error, response) => {
  if (!error) {
    console.log(`Greeting: ${response.getMessage()}`);
  } else {
    console.error(error);
  }
});

 

5- Ejecutar el Servidor y el Cliente

 

Inicia el servidor ejecutando node server.js y luego ejecuta el cliente con node client.js

 

javascript

 

Pasos para implementar gRPC en React

 

1- Configurar Servidor gRPC en node:

 

Antes de integrar gRPC en tu aplicación React, asegúrate de tener un servidor gRPC en funcionamiento. Puedes seguir los pasos anteriores para configurar un servidor gRPC en Node.js.

 

2- Configurar el Cliente gRPC en React

 

Instala las dependencias necesarias para el cliente gRPC en tu aplicación React

 

npm install grpc-web

 

3- Crear un Cliente gRPC en React

 

Se puede crear un cliente gRPC en react en un component o un servicio

 

import React, { useState } from 'react';
import { GreeterClient } from './generated/example_pb_service';
import { HelloRequest } from './generated/example_pb';

const GrpcExample = () => {
  const [response, setResponse] = useState('');

  const handleGrpcRequest = async () => {
    const request = new HelloRequest();
    request.setName('John Doe');

    const client = new GreeterClient('http://localhost:8080');

    client.sayHello(request, {}, (err, response) => {
      if (!err) {
        setResponse(response.getMessage());
      } else {
        console.error(err);
      }
    });
  };

  return (
    <div>
      <h1>gRPC Example in React</h1>
      <button onClick={handleGrpcRequest}>Make gRPC Request</button>
      <p>Response: {response}</p>
    </div>
  );
};

export default GrpcExample;

 

4- Configurar el Proxy para gRPC-Web

 

Como gRPC-Web no es compatible directamente con el navegador, necesitarás configurar un proxy para redirigir las solicitudes gRPC-Web al servidor gRPC. Puedes utilizar grpcwebproxy para esto

 

Instala e inicia grpcwebproxy y ejecuta la aplicación react

 

go get github.com/improbable-eng/grpc-web/go/grpcwebproxy

grpcwebproxy --backend_addr=localhost:50051 --run_tls_server=false --allow_all_origins

npm start

 

javascript

 

Patrón de cola de mensajes (Message Queue)

 

El patrón de Cola de Mensajes (Message Queue) es un patrón de comunicación entre componentes o sistemas que implica el envío y recepción de mensajes a través de una cola compartida. Este patrón es útil para desacoplar componentes, permitiéndoles comunicarse de manera asíncrona sin depender directamente unos de otros. Varios frameworks y bibliotecas de JavaScript proporcionan implementaciones y soporte para el patrón de Cola de Mensajes.

 

Message Queue en Node JS

 

Implementar el patrón de Cola de Mensajes en Node.js puede realizarse utilizando diversas bibliotecas y servicios. Una práctica común es utilizando RabbitMQ y la biblioteca amqplib, que es mayormente utilizada en entornos Node.js para interactuar con RabbitMQ. Asegúrate de tener RabbitMQ instalado y en ejecución localmente.

 

1- Instalacion de amqplib

 

npm install amqplib

 

2- Definir emisor

 

const amqp = require('amqplib');

async function enviarMensaje() {
  const connection = await amqp.connect('amqp://localhost');
  const channel = await connection.createChannel();

  const cola = 'mi_cola';
  const mensaje = 'Hola, este es un mensaje en la cola';

  await channel.assertQueue(cola, { durable: false });
  channel.sendToQueue(cola, Buffer.from(mensaje));

  console.log(`Mensaje enviado: ${mensaje}`);

  setTimeout(() => {
    connection.close();
  }, 500);
}

enviarMensaje();

 

3- consumidor

 

const amqp = require('amqplib');

async function recibirMensaje() {
  const connection = await amqp.connect('amqp://localhost');
  const channel = await connection.createChannel();

  const cola = 'mi_cola';

  await channel.assertQueue(cola, { durable: false });

  console.log(`Esperando mensajes en la cola ${cola}`);

  channel.consume(cola, (mensaje) => {
    console.log(`Mensaje recibido: ${mensaje.content.toString()}`);
  }, { noAck: true });
}

recibirMensaje();

 

Estos ejemplos son simples y utilizan RabbitMQ como backend, pero el patrón de Cola de Mensajes se puede implementar con otras soluciones, como Apache Kafka, Redis o servicios en la nube como AWS SQS o Google Cloud Pub/Sub, según los requisitos específicos de la aplicación.

 

javascript

 

Message Queue en Angular

 

En Angular, la implementación de un sistema de Message Queue (Cola de Mensajes) generalmente se lleva a cabo utilizando servicios y observables para facilitar la comunicación entre componentes de manera desacoplada. Aunque Angular no tiene una implementación nativa de colas de mensajes como en algunos sistemas de backend, puedes lograr un patrón similar usando los servicios y observables proporcionados por Angular.

 

Pasos para emular un patron de mensajes en cola

 

1- Crear un servicio de Message Queue

 

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class MessageQueueService {
  private messageSubject = new Subject<any>();

  sendMessage(message: any) {
    this.messageSubject.next(message);
  }

  getMessage(): Observable<any> {
    return this.messageSubject.asObservable();
  }
}

 

2- Productor (Componente Emisor)

 

import { Component } from '@angular/core';
import { MessageQueueService } from './message-queue.service';

@Component({
  selector: 'app-productor',
  template: `
    <button (click)="enviarMensaje()">Enviar Mensaje</button>
  `,
})
export class ProductorComponent {
  constructor(private messageQueueService: MessageQueueService) {}

  enviarMensaje() {
    const mensaje = 'Hola desde el componente productor';
    this.messageQueueService.sendMessage(mensaje);
  }
}

 

3- Consumidor (Componente Receptor)

 

import { Component, OnDestroy } from '@angular/core';
import { MessageQueueService } from './message-queue.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-consumidor',
  template: `
    <p>Mensaje recibido: {{ mensajeRecibido }}</p>
  `,
})
export class ConsumidorComponent implements OnDestroy {
  mensajeRecibido: any;
  private subscription: Subscription;

  constructor(private messageQueueService: MessageQueueService) {
    this.subscription = this.messageQueueService.getMessage().subscribe((mensaje) => {
      this.mensajeRecibido = mensaje;
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

 

4- Configurar Módulo de Angular

 

import { NgModule } from '@angular/core';
import { ProductorComponent } from './productor.component';
import { ConsumidorComponent } from './consumidor.component';
import { MessageQueueService } from './message-queue.service';

@NgModule({
  declarations: [ProductorComponent, ConsumidorComponent],
  providers: [MessageQueueService],
})
export class AppModule {}

 

Con este enfoque, el servicio MessageQueueService actúa como una cola de mensajes. El componente emisor (ProductorComponent) utiliza el servicio para enviar mensajes, y el componente receptor (ConsumidorComponent) se suscribe al servicio para recibir y procesar esos mensajes.

 

javascript

 

Patrón de cola de mensajes (Message Passing)

 

El patrón de Paso de Mensajes (Message Passing) es un enfoque en el que los distintos componentes de un sistema se comunican enviándose mensajes. Este patrón es comúnmente utilizado en sistemas basados en eventos, donde los componentes interactúan de manera asincrónica y desacoplada. En el contexto de JavaScript, especialmente en frameworks y bibliotecas, este patrón se implementa a menudo mediante el uso de eventos, observables o técnicas similares. 

 

Message passing en Angular

 

1- Crear un servicio de Mensajes:

 

// message.service.ts
import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class MessageService {
  private messageSubject = new Subject<any>();

  sendMessage(message: any) {
    this.messageSubject.next(message);
  }

  getMessage(): Observable<any> {
    return this.messageSubject.asObservable();
  }
}

 

2- Componente Emisor (Productor):

 

// producer.component.ts
import { Component } from '@angular/core';
import { MessageService } from './message.service';

@Component({
  selector: 'app-producer',
  template: `
    <button (click)="sendMessage()">Enviar Mensaje</button>
  `,
})
export class ProducerComponent {
  constructor(private messageService: MessageService) {}

  sendMessage() {
    const message = 'Hola desde el componente emisor';
    this.messageService.sendMessage(message);
  }
}

 

3- Componente Receptor (Consumidor):

 

// consumer.component.ts
import { Component, OnDestroy } from '@angular/core';
import { MessageService } from './message.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-consumer',
  template: `
    <p>Mensaje recibido: {{ receivedMessage }}</p>
  `,
})
export class ConsumerComponent implements OnDestroy {
  receivedMessage: any;
  private subscription: Subscription;

  constructor(private messageService: MessageService) {
    this.subscription = this.messageService.getMessage().subscribe((message) => {
      this.receivedMessage = message;
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

 

4- Configurar el Módulo Angular:

 

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ProducerComponent } from './producer.component';
import { ConsumerComponent } from './consumer.component';
import { MessageService } from './message.service';

@NgModule({
  imports: [BrowserModule],
  declarations: [ProducerComponent, ConsumerComponent],
  providers: [MessageService],
  bootstrap: [ProducerComponent, ConsumerComponent],
})
export class AppModule {}

 

El servicio MessageService actúa como un canal de mensajes. El componente emisor (ProducerComponent) utiliza el servicio para enviar mensajes, y el componente receptor (ConsumerComponent) se suscribe al servicio para recibir y procesar esos mensajes.

 

javascript

 

Message Passing en React

 

En React, el patrón de paso de mensajes se implementa típicamente a través de la propagación de props y el uso de funciones de devolución de llamada (callbacks) o, en casos más avanzados, mediante la utilización de contextos o la gestión de estados con estados globales (Redux, Recoil, etc.). 

 

Paso de mensajes mediante Props: 

 

1- Componente Emisor (Productor):

 

import React from 'react';

const Productor = ({ enviarMensaje }) => (
  <button onClick={() => enviarMensaje('Hola desde el componente emisor')}>Enviar Mensaje</button>
);

 

2- Componente Receptor (Consumidor):

 

import React from 'react';

const Consumidor = ({ mensajeRecibido }) => (
  <p>Mensaje recibido: {mensajeRecibido}</p>
);

 

3- Componente Principal:

 

import React, { useState } from 'react';
import Productor from './Productor';
import Consumidor from './Consumidor';

const App = () => {
  const [mensaje, setMensaje] = useState('');

  const recibirMensaje = (mensaje) => {
    setMensaje(mensaje);
  };

  return (
    <div>
      <Productor enviarMensaje={recibirMensaje} />
      <Consumidor mensajeRecibido={mensaje} />
    </div>
  );
};

export default App;

 

javascript

 

Patron de middleware

 

El patrón de middleware es comúnmente utilizado en muchos frameworks y librerías de JavaScript para gestionar el flujo de ejecución y realizar tareas intermedias en el procesamiento de solicitudes o eventos. 

 

Express NodeJs

 

En Express.js, un middleware es una función que tiene acceso a los objetos de solicitud (req), respuesta (res), y la siguiente función en la cadena de middleware (next). Puedes utilizar múltiples middlewares para procesar una solicitud en orden.

 

const express = require('express');
const app = express();

// Middleware
const loggerMiddleware = (req, res, next) => {
  console.log(`Solicitud recibida: ${req.method} ${req.url}`);
  next(); // Llama a la siguiente función de middleware en la cadena
};

// Usa el middleware para todas las rutas
app.use(loggerMiddleware);

// Ruta principal
app.get('/', (req, res) => {
  res.send('Hola, mundo!');
});

app.listen(3000, () => {
  console.log('Servidor escuchando en el puerto 3000');
});

 

Koa.js (Node.js):

 

Koa.js es un framework web más moderno construido sobre las lecciones aprendidas de Express.js. Utiliza middlewares de una manera más eficiente y utiliza funciones asíncronas.

 

const Koa = require('koa');
const app = new Koa();

// Middleware
const loggerMiddleware = async (ctx, next) => {
  console.log(`Solicitud recibida: ${ctx.method} ${ctx.url}`);
  await next(); // Llama a la siguiente función de middleware en la cadena
};

// Usa el middleware
app.use(loggerMiddleware);

// Ruta principal
app.use(async (ctx) => {
  ctx.body = 'Hola, mundo!';
});

app.listen(3000, () => {
  console.log('Servidor escuchando en el puerto 3000');
});

 

Redux (React)

 

En el contexto de React y Redux, los middlewares son funciones que se intercalan entre la acción que se despacha y el momento en que llega al reducer. Permiten realizar tareas adicionales, como manejar acciones asíncronas, realizar logs, o incluso modificar la acción antes de que alcance al reducer.

 

Un middleware en Redux sigue el siguiente formato:

 

const miMiddleware = (store) => (next) => (action) => {
  // Código del middleware
  next(action); // Llama al siguiente middleware o al reducer
};

 

En React y Redux, uno de los middlewares más comúnmente utilizado es redux-thunk. Este middleware permite manejar acciones asíncronas y devuelve funciones desde los creadores de acciones en lugar de objetos simples. A continuación, un ejemplo básico de cómo usar redux-thunk:

 

Instalación de Redux Thunk

 

npm install redux-thunk

 

Configuración de redux-thunk

 

// store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers'; // Importa tu rootReducer aquí

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

export default store;

 

Uso de redux-thunk

 

// actions.js
const fetchDataStart = () => ({
  type: 'FETCH_DATA_START',
});

const fetchDataSuccess = (data) => ({
  type: 'FETCH_DATA_SUCCESS',
  payload: data,
});

const fetchDataError = (error) => ({
  type: 'FETCH_DATA_ERROR',
  payload: error,
});

// El siguiente creador de acciones devuelve una función gracias a redux-thunk
const fetchData = () => {
  return async (dispatch) => {
    dispatch(fetchDataStart());

    try {
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();
      dispatch(fetchDataSuccess(data));
    } catch (error) {
      dispatch(fetchDataError(error));
    }
  };
};

export { fetchData };

 

En este ejemplo, fetchData es un creador de acciones que, gracias a redux-thunk, puede devolver una función en lugar de un objeto de acción. Esta función puede realizar operaciones asíncronas y despachar otras acciones en diferentes momentos del proceso.

 

javascript

 

Patrón de inyección de dependencias (Dependency Injection)

 

El patrón de Inyección de Dependencias (DI, por sus siglas en inglés Dependency Injection) es una técnica en la que un objeto recibe sus dependencias de una fuente externa en lugar de crearlas internamente. Este patrón es comúnmente utilizado en frameworks y librerías de programación para mejorar la modularidad y la prueba unitaria, y es fundamental en el desarrollo de aplicaciones basadas en inversion de control (IoC).

 

DI en Angular

 

En Angular, la Inyección de Dependencias es un concepto central. Angular tiene su propio sistema de Inyección de Dependencias que permite la creación y gestión de instancias de servicios.

 

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class MiServicio {
  // Lógica del servicio
}

 

En este ejemplo, @Injectable marca la clase como un servicio que Angular puede inyectar automáticamente cuando sea necesario. El uso de providedIn: 'root' significa que este servicio es singleton y está disponible en toda la aplicación.

 

DI en Node

 

En Node.js, la Inyección de Dependencias puede ser realizada manualmente o utilizando bibliotecas como InversifyJS o Awilix. 

 

class MiServicio {
  // Lógica del servicio
}

class MiComponente {
  constructor(miServicio) {
    this.miServicio = miServicio;
  }

  // Lógica del componente usando this.miServicio
}

const miServicio = new MiServicio();
const miComponente = new MiComponente(miServicio);

 

En este ejemplo, MiComponente recibe MiServicio como una dependencia que debe ser proporcionada externamente.

 

Patrón de Puente (Bridge):

 

El patrón de Puente (Bridge) es un patrón estructural que separa una abstracción de su implementación, permitiendo que ambas evolucionen de manera independiente. Este patrón es útil cuando tienes varias dimensiones de variación y deseas evitar una explosión combinatoria de clases, proporcionando una interfaz más flexible.

 

En el contexto de los frameworks JavaScript, el patrón de Puente puede aplicarse para desacoplar componentes y facilitar la extensión y la variación de funcionalidades.

 

// Implementación de la interfaz (Implementor)
class DibujoAPI {
  dibujarCirculo(x, y, radio) {
    console.log(`Dibujando un círculo en (${x}, ${y}) con radio ${radio}`);
  }
}

// Abstracción (Abstraction)
class Forma {
  constructor(dibujoAPI) {
    this.dibujoAPI = dibujoAPI;
  }

  dibujar() {
    // Implementación común
  }

  redimensionar(factor) {
    // Implementación común
  }
}

// Abstracción refinada (Refined Abstraction)
class Circulo extends Forma {
  constructor(x, y, radio, dibujoAPI) {
    super(dibujoAPI);
    this.x = x;
    this.y = y;
    this.radio = radio;
  }

  dibujar() {
    this.dibujoAPI.dibujarCirculo(this.x, this.y, this.radio);
  }

  redimensionar(factor) {
    this.radio *= factor;
  }
}

// Uso del patrón de Puente
const dibujoAPIV1 = new DibujoAPI();
const circuloV1 = new Circulo(1, 2, 3, dibujoAPIV1);
circuloV1.dibujar(); // Dibujando un círculo en (1, 2) con radio 3
circuloV1.redimensionar(2);
circuloV1.dibujar(); // Dibujando un círculo en (1, 2) con radio 6

// Puedes introducir una nueva implementación sin modificar las clases existentes
class DibujoAPIV2 {
  dibujarCirculo(x, y, radio) {
    console.log(`Nueva implementación: Dibujando un círculo en (${x}, ${y}) con radio ${radio}`);
  }
}

const dibujoAPIV2 = new DibujoAPIV2();
const circuloV2 = new Circulo(4, 5, 6, dibujoAPIV2);
circuloV2.dibujar(); // Nueva implementación: Dibujando un círculo en (4, 5) con radio 6

 

En este ejemplo:

 

  • DibujoAPI es la interfaz de implementación que puede tener múltiples implementaciones.
  • Forma es la abstracción que se relaciona con DibujoAPI.
  • Circulo es una abstracción refinada que hereda de Forma y utiliza una implementación específica de DibujoAPI.
  • Este patrón permite cambiar las implementaciones de DibujoAPI sin afectar a las clases de formas existentes, proporcionando así una mayor flexibilidad y extensibilidad en el código.

 

Esta es una guía completa de los patrones de comunicación en JavaScript.

 

Te recomendamos en video