Padrão Proxy

O Padrão de Projeto Proxy possui três principais finalidades, sendo elas:

  • Prover um substituto para um outro objeto controlar seu acesso.

  • Usar um nível extra de indireção para fornecer acesso distribuído, controlado ou inteligente.

  • Adicionar um agregador e delegador para proteger o componente real de complexidade indevida.

Problema

Imagine uma situação onde temos uma conexão com bancos de dados por meio de um componente DAO e as operações providas por esse DAO só podem ser realizadas por um grupo específico de usuários.

public class DAOPessoaImpl implements DAOPessoa {

    public void salvar(Pessoa p) { ... }
    public void excluir(Pessoa p) { ... }
    public Pessoa consultar(Long pessoaId) { ... }
    public List<Pessoa> listar() { ...}

}

Como podemos fazer essa verificação? Uma vez que adicionar essa regra no próprio componente faria com que estivessemos quebrando o Princípio de Responsabilidade Única.

Solução

O Padrão Proxy tem como objetivo "fornecer um substituto ou marcador da localização de outro objeto para controlar o acesso a esse objeto". Se esse objeto Proxy visa ser um substituto, devemos ter a mesma interface do objeto que se pretende substituir, ou seja, DAOPessoa no nosso exemplo.

public class DAOPessoaProxy implements DAOPessoa {

    private DAOPessoa daoPessoaBase;
    
    public DAOPessoaProxy(DAOPessoa dao) {
        this.daoPessoaBase = dao;
    }

    public void salvar(Pessoa p) {
        // Verificar se é permitido realizar essa operação
        this.daoPessoaBase.salvar(p);
    }
    
    public void excluir(Pessoa p) {
        // Verificar se é permitido realizar essa operação
        this.daoPessoaBase.excluir(p);
    }
    
    public Pessoa consultar(Long pessoaId) {
        // Verificar se é permitido realizar essa operação
        this.daoPessoaBase.consultar(pessoaId);
    }
    
    public List<Pessoa> listar() {
        // Verificar se é permitido realizar essa operação
        this.daoPessoaBase.listar();
    }

}

Veja que temos os mesmos métodos, mas ao invés de implementá-los como um DAO padrão, fazemos apenas as verificações necessárias antes de executar de fato o método do objeto que estamos envolvendo (daoPessoaBase). Dessa maneira, esse Proxy pode envolver e controlar o acesso de qualquer classe concreta que venha a partir da interface DAOPessoa.

Um pouco mais sobre Proxy

Embora esse exemplo acima seja extremamente simples, apenas pra fins didáticos, é preciso comentar um pouco sobre os tipos de proxy que podem ser utilizados:

  • Protection Proxy: esse é o tipo de proxy que utilizamos no exemplo. Eles controlam o acesso aos objetos, por exemplo, verificando se quem chama possui a devida permissão.

  • Virtual Proxy: mantem informações sobre o objeto real, adiando o acesso/criação do objeto em si.

  • Remote Proxy: fornece um representante local para um objeto em outro espaço de endereçamento.

  • Smart Reference: este proxy é apenas um susbtituto simples para executar ações adicionais quando o objeto é acessado, por exemplo para implementar mecanismos de sincronização de acesso ao objeto original.

Cada proxy implicaria em um design diferente. A principal vantagem de utilizar o Proxy é que, ao utilizar um substituto, podemos fazer desde operações otimizadas até proteção do acesso ao objeto. No entanto isto também pode ser visto como um problema, pois, como a responsabilidade de um proxy não é bem definida é necessário conhecer bem seu comportamento para decidir quando utilizá-lo ou não.

Last updated

Was this helpful?