Conheça o Pattern Proxy - GoF (Gang of Four)

Veja neste artigo como funciona o pattern Proxy, um pattern estrutural definido pelo GoF (Gang of Four) e cujo objetivo principal é encapsular um objeto através de um outro objeto que possui a mesma interface.

O Pattern Proxy é um padrão Estrutural definido pelo GoF (Gang of Four). O seu objetivo principal é encapsular um objeto através de um outro objeto que possui a mesma interface, de forma que o segundo objeto, conhecido como “Proxy”, controla o acesso ao primeiro, que é o objeto real.

Vantagens do Pattern Proxy

As principais vantagens de se utilizar o pattern Proxy são:

Uma vez que neste padrão o objeto real é encapsulado, o objeto Proxy pode armazenar o resultado de um acesso em cache. Por exemplo, se um Remote Proxy é utilizado, o custo deste acesso remoto pode ser grande para a aplicação, neste caso o Proxy salva localmente os resultados em cache, diminuindo assim, a quantidade de acessos remotos.

Diagrama

Abaixo o diagrama do pattern Proxy:

Figura 1. Diagrama do padrão Proxy

O diagrama demonstra que o objeto Proxy e o objeto real (RealSubject) implementam a mesma interface, neste caso chamada de Subject. O Proxy encapsula o acesso ao RealSubject.

Exemplo de Código

Abaixo temos um exemplo de código. Crie uma classe “ProxyExample” e execute o código:

import java.util.ArrayList; import java.util.List; /** * Imagine que esta classe faz acessos ao banco de dados */ class PessoaDAO { public static Pessoa getPessoaByID(String id){ System.out.println("select * from PESSOA where id="+id); return new PessoaImpl(id,"Pessoa " + id); } } /** * Interface comum entre o objeto real e o Proxy */ interface Pessoa { public String getNome(); public String getId(); } /** * Objeto real */ class PessoaImpl implements Pessoa { private String nome; private String id; public PessoaImpl(String id,String nome) { this.id = id; this.nome = nome; // apenas para simular algo... System.out.println("Retornou a pessoa do banco de dados -> " + nome); } public String getNome() { return nome; } public String getId() { return this.id; } } class ProxyPessoa implements Pessoa { private String id; private Pessoa pessoa;//mesma interface public ProxyPessoa(String nome) { this.id = nome; } /** * Método comum da interface * * @see Pessoa#getNome() */ public String getNome() { if (pessoa == null) { //Apenas cria o objeto real quando chamar este método pessoa = PessoaDAO.getPessoaByID(this.id); } /** Delega para o objeto real **/ return pessoa.getNome(); } public String getId() { return this.id; } } /** * Exemplo adaptado de "http://en.wikipedia.org/wiki/Proxy_pattern" */ public class ProxyExample { public static void main(String[] args) { List<Pessoa> pessoas = new ArrayList<Pessoa>(); //Cria cada Proxy para encapsular o acesso a classe "PessoaImpl" pessoas.add(new ProxyPessoa("A")); pessoas.add(new ProxyPessoa("B")); pessoas.add(new ProxyPessoa("C")); System.out.println("Nome: " + pessoas.get(0).getNome()); // busca do banco de dados System.out.println("Nome: " + pessoas.get(1).getNome()); // busca do banco de dados System.out.println("Nome: " + pessoas.get(0).getNome()); // já buscou esta pessoa... apenas retorna do cache... // A terceira pessoa nunca será consultada no banco de dados (melhor performance - lazy loading) System.out.println("Id da 3ª - " + pessoas.get(2).getId()); //pode imprimir o ID do objeto, e o proxy nao será inicializado. } }
Listagem 1. Exemplo de código do padrão Proxy

A saída do programa é a seguinte:

select * from PESSOA where id=A Retornou a pessoa do banco de dados -> Pessoa A Nome: Pessoa A select * from PESSOA where id=B Retornou a pessoa do banco de dados -> Pessoa B Nome: Pessoa B Nome: Pessoa A Id da 3ª – C
Listagem 2. Saída o programa

Conforme demonstrado no exemplo, uma consulta ao banco de dados é realizada apenas quando o método getNome da Pessoa é chamado. O Proxy controla este acesso, controlando a consulta para esta ser realizada apenas uma vez.

Note que o método pessoas.get(2).getId() foi chamado para imprimir o ID da “Pessoa C”, e isto não inicializou o proxy.

Lembre-se: o importante é que o Proxy e o objeto real que está sendo encapsulado devem implementar a mesma interface.

Conclusão

O Pattern Proxy é muito utilizado em aplicações J2EE e por alguns frameworks, espero que tenham gostado deste breve artigo, e até a próxima.

Artigos relacionados