En mis blogs anteriores, exploré varios patrones de diseño creativo que tratan con mecanismos de creación de objetos. Ahora es el momento de sumergirnos en patrones de diseño estructural, que se centran en cómo se componen los objetos y las clases para formar estructuras más grandes y al mismo tiempo mantenerlas flexibles y eficientes. Comencemos con el patrón de diseño de proxy
El patrón de diseño Proxy es un patrón de diseño estructural que proporciona un objeto que representa otro objeto. Actúa como un intermediario que controla el acceso al objeto real, añadiendo comportamientos adicionales como inicialización diferida, registro, control de acceso o almacenamiento en caché, sin cambiar el código del objeto original.
En JavaScript, los servidores proxy son funciones integradas proporcionadas por el objeto Proxy, lo que le permite definir un comportamiento personalizado para operaciones fundamentales como acceso a propiedades, asignación, invocación de funciones, etc.
El patrón Proxy es particularmente útil cuando:
Imagina que tienes un cuadro grande que quieres mostrar a tus invitados, pero te lleva mucho tiempo sacarlo de un cuarto de almacenamiento (porque es pesado y toma tiempo transportarlo). En lugar de esperar eso cada vez, decides usar una pequeña imagen postal de la pintura para mostrársela rápidamente mientras esperan que traigan la pintura real.
En esta analogía:
Piense en un agente de bienes raíces como un apoderado. Cuando quieres comprar una casa, no visitas todas las casas inmediatamente (cargando el objeto real). En cambio, el agente inmobiliario (representante) primero le muestra fotos y descripciones. Solo cuando esté listo para comprar (es decir, cuando llame a display()), el agente organiza una visita a la casa (carga el objeto real).
Usemos el ejemplo de carga de imágenes en una aplicación web donde queremos retrasar la carga de la imagen hasta que el usuario la solicite (carga diferida). Un proxy puede actuar como marcador de posición hasta que se carga la imagen real.
A continuación se explica cómo implementar el patrón de diseño Proxy en JavaScript.
// Step 1: The real object class RealImage { constructor(filename) { this.filename = filename; this.loadImageFromDisk(); } loadImageFromDisk() { console.log(`Loading ${this.filename} from disk...`); } display() { console.log(`Displaying ${this.filename}`); } } // Step 2: The proxy object class ProxyImage { constructor(filename) { this.realImage = null; // no real image yet this.filename = filename; } display() { if (this.realImage === null) { // load the real image only when needed this.realImage = new RealImage(this.filename); } this.realImage.display(); // display the real image } } // Step 3: Using the proxy to display the image const image = new ProxyImage("photo.jpg"); image.display(); // Loads and displays the image image.display(); // Just displays the image (already loaded)
Explicación:
1). La imagen real:
2). La imagen proxy:
3). Uso:
El proxy ES6 consta de un constructor de proxy que acepta un objetivo y un controlador como argumentos
const proxy = new Proxy(target, handler)
Aquí, el objetivo representa el objeto sobre el cual se aplica el proxy, mientras que el controlador es un objeto especial que define el comportamiento del proxy.
El objeto controlador contiene una serie de métodos opcionales con nombres predefinidos llamados métodos trap (por ejemplo, aplicar, obtener, establecer y tiene) que se llaman automáticamente cuando se realizan las operaciones correspondientes en la instancia de proxy.
Entendamos esto implementando la calculadora usando el proxy integrado
// Step 1: Define the Calculator class with prototype methods class Calculator { constructor() { this.result = 0; } // Prototype method to add numbers add(a, b) { this.result = a b; return this.result; } // Prototype method to subtract numbers subtract(a, b) { this.result = a - b; return this.result; } // Prototype method to multiply numbers multiply(a, b) { this.result = a * b; return this.result; } // Prototype method to divide numbers divide(a, b) { if (b === 0) throw new Error("Division by zero is not allowed."); this.result = a / b; return this.result; } } // Step 2: Create a proxy handler to intercept operations const handler = { // Intercept 'get' operations to ensure access to prototype methods get(target, prop, receiver) { if (prop in target) { console.log(`Accessing property: ${prop}`); return Reflect.get(target, prop, receiver); // Access property safely } else { throw new Error(`Property "${prop}" does not exist.`); } }, // Intercept 'set' operations to prevent mutation set(target, prop, value) { throw new Error(`Cannot modify property "${prop}". The calculator is immutable.`); } }; // Step 3: Create a proxy instance that inherits the Calculator prototype const calculator = new Calculator(); // Original calculator object const proxiedCalculator = new Proxy(calculator, handler); // Proxy wrapping the calculator // Step 4: Use the proxy instance try { console.log(proxiedCalculator.add(5, 3)); // Output: 8 console.log(proxiedCalculator.multiply(4, 2)); // Output: 8 console.log(proxiedCalculator.divide(10, 2)); // Output: 5 // Attempt to access prototype directly through proxy console.log(proxiedCalculator.__proto__ === Calculator.prototype); // Output: true // Attempt to modify a property (should throw an error) proxiedCalculator.result = 100; // Error: Cannot modify property "result". } catch (error) { console.error(error.message); // Output: Cannot modify property "result". The calculator is immutable. }
La mejor parte es usar proxy de esta manera:
- El objeto proxy hereda el prototipo de la clase Calculadora original.
- Las mutaciones se evitan mediante la trampa del Proxy.
Explicación del Código
1). Herencia del prototipo:
2). Manejo de getOperations:
3). Prevención de mutaciones:
La trampa establecida arroja un error cada vez que se intenta modificar cualquier propiedad en el objeto de destino. Esto garantiza la inmutabilidad.
4). Uso de métodos de prototipo a través del proxy:
El proxy permite el acceso a métodos como sumar, restar, multiplicar y dividir, todos los cuales están definidos en el prototipo del objeto original.
Los puntos clave a observar aquí son:
Si has llegado hasta aquí, no olvides darle a Me gusta ❤️ y dejar un comentario a continuación con cualquier pregunta o idea. ¡Tus comentarios significan mucho para mí y me encantaría saber de ti!
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3