Em meus blogs anteriores, explorei vários padrões de design criativo que lidam com mecanismos de criação de objetos. Agora é hora de mergulhar nos padrões de design estrutural, que se concentram em como objetos e classes são compostos para formar estruturas maiores, mantendo-as flexíveis e eficientes. Vamos começar com o padrão de design de proxy
O padrão de design Proxy é um padrão de design estrutural que fornece um objeto que representa outro objeto. Ele atua como um intermediário que controla o acesso ao objeto real, adicionando comportamento adicional, como inicialização lenta, registro em log, controle de acesso ou cache, sem alterar o código do objeto original.
Em JavaScript, proxies são recursos integrados fornecidos pelo objeto Proxy, permitindo definir comportamento personalizado para operações fundamentais, como acesso a propriedades, atribuição, invocação de função, etc.
O padrão Proxy é particularmente útil quando:
Imagine que você tem uma pintura grande que deseja mostrar aos seus convidados, mas leva muito tempo para retirá-la de um depósito (porque é pesada e demora para carregar). Em vez de esperar por isso todas as vezes, você decide usar uma pequena imagem de cartão postal da pintura para mostrá-los rapidamente enquanto esperam que a pintura real seja buscada.
Nesta analogia:
Pense em um corretor de imóveis como um procurador. Quando você quer comprar uma casa, você não visita imediatamente todas as casas (carregando o objeto real). Em vez disso, o agente imobiliário (proxy) mostra primeiro fotos e descrições. Somente quando você estiver pronto para comprar (ou seja, quando você ligar para display()), o agente marcará uma visita domiciliar (carrega o objeto real).
Vamos usar o exemplo de carregamento de imagem em uma aplicação web onde queremos atrasar o carregamento da imagem até que o usuário solicite (carregamento lento). Um proxy pode atuar como um espaço reservado até que a imagem real seja carregada.
Veja como você pode implementar o padrão de design Proxy em 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)
Explicação:
1). A imagem real:
2). A imagem proxy:
3). Uso:
O proxy ES6 consiste em um construtor de proxy que aceita um alvo e um manipulador como argumentos
const proxy = new Proxy(target, handler)
Aqui, target representa o objeto no qual o proxy é aplicado, enquanto handler é um objeto especial que define o comportamento do proxy.
O objeto manipulador contém uma série de métodos opcionais com nomes predefinidos chamados métodos trap (por exemplo, apply,get,set e has) que são chamados automaticamente quando as operações correspondentes são executadas na instância do proxy.
Vamos entender isso implementando a calculadora usando 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. }
A melhor parte de usar proxy desta forma como:
- O objeto proxy herda o protótipo da classe Calculadora original.
- Mutações são evitadas através da armadilha definida do Proxy.
Explicação do Código
1). Herança do protótipo:
2). Tratando getOperations:
3). Prevenindo mutações:
O set trap gera um erro sempre que há uma tentativa de modificar qualquer propriedade no objeto de destino. Isso garante imutabilidade.
4). Usando métodos de protótipo por meio do proxy:
O proxy permite acesso a métodos como adição, subtração, multiplicação e divisão, todos definidos no protótipo do objeto original.
Os principais pontos a serem observados aqui são:
Se você chegou até aqui, não se esqueça de clicar em curtir ❤️ e deixar um comentário abaixo com qualquer dúvida ou opinião. Seu feedback significa muito para mim e adoraria ouvir de você!
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3