Com o Padrão de Projeto Proxy você consegue controlar o acesso a um objeto de modo a prover somente as funções permitidas a um determinado cliente. Ou seja, ele encapsula um objeto que possui a mesma implementação de interface de um segundo objeto, chamado proxy, que controla o acesso ao primeiro.
Veja no diagrama de classe e observe que esse pattern é basicamente uma classe que representa outra classe, neste caso o Objeto Real que terá o seu acesso controlado pelo Objeto Proxy. Observe também que da forma que este padrão foi pensado, você poderá criar mais de um proxy para um determinado RealSubject e criar uma espécie de encadeamento.
Certamente em algum momento você esbarrou em algum Proxy de internet. Como poderíamos representar essa implementação, por exemplo, de controle de conexão com a internet?
A estrutura de uso deste padrão neste exemplo de controle de conexão, o contrato do Subject fica sendo a ação de conexão a um determinado site. Ou seja, se o site estiver na lista de negados, disparará uma exceção. Caso contrário, aparecerá uma mensagem com o sucesso da conexão.
<?php declare(strict_types=1); namespace Growthdev\DesignPatterns\Structural\Proxy; final class Site { public readonly string $url; public function __construct(string $url) { $this->url = $url; } }
<?php declare(strict_types=1); namespace Growthdev\DesignPatterns\Structural\Proxy; interface Internet { public function connectTo(Site $site): void; }
<?php declare(strict_types=1); namespace Growthdev\DesignPatterns\Structural\Proxy; class RealInternet implements Internet { public function connectTo(Site $site): void { printf("Connected to %s", $site->url); } }
<?php declare(strict_types=1); namespace Growthdev\DesignPatterns\Structural\Proxy; use Exception; final class ProxyInternet implements Internet { private Internet $internet; private array $bannedSites = [ 'http://xxxvideos.com', 'http://xtzsite.com', 'http://redsite.com', 'http://sitetube.com' ]; public function __construct() { $this->internet = new RealInternet(); } public function connectTo(Site $site): void { if (in_array($site->url, $this->bannedSites)) { throw new Exception('Access denied'); } $this->internet->connectTo($site); } }
Esse exemplo nos dá uma noção muito boa de como utilizar este Padrão de Projeto. Acho o seu uso bastante simples e intuitivo. Observe nos testes a seguir que a classe Proxy Internet se tornou uma espécie de invólucro, ou seja, efetuou um “envelopamento” da classe Real Internet. Por esse motivo, podemos dizer que essa é uma classe wrapper.
<?php declare(strict_types=1); namespace Growthdev\DesignPatterns\Tests\Structural\Proxy; use Exception; use Growthdev\DesignPatterns\Structural\Proxy\ProxyInternet; use Growthdev\DesignPatterns\Structural\Proxy\Site; use PHPUnit\Framework\TestCase; final class ProxyTest extends TestCase { public function testExpectAccessToTheSiteDenied(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('Access denied'); $internet = new ProxyInternet(); $internet->connectTo(new Site('http://xxxvideos.com')); } public function testExpectAccessToTheSiteGranted(): void { $internet = new ProxyInternet(); $internet->connectTo(new Site('https://growthcode.com.br')); $this->expectOutputString('Connected to https://growthcode.com.br'); } }
Esse padrão de projeto estrutural é largamente utilizado. Se você quiser aprender sobre os outros padrões do livro GOF, veja no artigo Resumo dos Padrões de Projetos. Além disso, todos os códigos dos exemplos estou disponibilizando no meu Github:
https://github.com/growthdev-repo/design-patterns
Espero que você esteja gostando desta série de artigos. Até o próximo!
Confiança Sempre!!!
Fontes:
- [1] GAMMA, Erich et al. Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos.
- https://www.geeksforgeeks.org/proxy-design-pattern/
Seja o primeiro a comentar