Duvidas Pattern Proxy

25 respostas
A

Olha se alguém puder me explicar qual a verdadeira finalidade do Pattern Proxy eu agradeço, ja pesquisei e não encontrei nenhum o unico que vi não teve resposta.

nas pesquisas que realizei encontrei que o pattern proxy encapsula uma classe a qual ele faz referencia e deve utilizar-se da mesma interface de tal classe,

existe o proxy remoto, virtual proxy, mas preciso saber a necessidade de se utilizar o proxy?

25 Respostas

xjunior

Imagine que vc possui um objeto ou método que é altamente custoso ou complexo, e ainda, vc fará esta implementação em diferentes partes do seu código. Então o pattern proxy é recomendado para isto, em situações em que várias cópias que deve existir um objeto complexo, ele pode ser adaptado para incorporar o padrão de contrapeso, a fim de reduzir o consumo de memória da aplicação e consequentemente melhorar a performance e auxiliar na melhoria da manutenabilidade.

Ele funciona da seguinte forma:

Uma instância do objeto complexo é criado e são criados vários objetos proxy, pelos quais contêm uma única referência ao objeto original complexo e todas as interações com os objetos proxys são interadas ao objeto original complexo, uma vez que quando se utiliza os objetos proxys é liberada a memória do objeto complexo, uma vez que estes estão fora do escopo.

Não sei se fui claro o suficiente, mas creio que era esta explicação que vc queria, ok?

ViniGodoy

O proxy é uma classe que controla acesso à outra classe.

A

Bem não sei se compreendi bem o que você disse, mas então que dizer que funciona assim exemplo:

Tenho uma classe que busca no banco uma imagem muito grande, então crio um proxy desta classe assim posso Instanciar o objeto real pela proxy somente quando necessário asim não alocando a memória antecipadamente
seria isso?

xjunior

acidburn:
Bem não sei se compreendi bem o que você disse, mas então que dizer que funciona assim exemplo:

Tenho uma classe que busca no banco uma imagem muito grande, então crio um proxy desta classe assim posso Instanciar o objeto real pela proxy somente quando necessário asim não alocando a memória antecipadamente
seria isso?

???

leia atentamente o que eu escrevi, se não entender, vou dar um exemplo mais simples, vc quer uma implementação para vc testar?

A

O exemplo que estou tentando intender:

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.
      }
}

exemplo tirado do DevMedia postado por Ricardo Rodrigues

A

Segue explicação: do mesmo lugar referenciado a cima

Abaixo a saída do programa:

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

Conforme demonstrado no exemplo, uma consulta no 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.

xjunior

mano, favor editar seu post e colocar o código fonte dentro da tag “code”…

A

Valeu pela dica, esta editado

P

Um bom exemplo de aplicação de Proxy para funcionalidade, ao invés de economia, ocorre em frameworks de “remoting”.
Como uma referência direta à memória de outro processo é impossível, o programa local faz referência a um objeto Proxy ao invés; e o Proxy oculta a solução para o problema de comunicação entre processos.

Qualquer objeto que está para um sistema externo – como um conector de banco de dados – pode ser considerado um Proxy do sistema externo no programa local.
Note que “proxy” é inglês para “procurador” – uma pessoa legalmente habilitada a agir em nome de outra.

xjunior

então, de forma resumida::

Um proxy é um “passo” intermediário de um fluxo.
O proxy determina quando o objeto deve ser construído ou representado.
O Proxy serve para criar um substituto do objeto original.

Acho que entendi a sua concepção, vc disse sobre a imagem pois vc quer criar um objeto proxy para gerenciar a carga da imagem, aí sim está correto, o proxy pode te ajudar nisso…

Proxy remoto (Remote Proxy) - providencia um representante local de um objeto que se encontra num espaço de endereçamento diferente.
Proxy virtual (Virtual Proxy)- cria objetos dispendiosos apenas por pedido (on demand).
Proxy de proteção (Protection Proxy)- controla o acesso ao objeto original.

Qual tipo vc está querendo implementar?

A

pedro.lamarao:
Um bom exemplo de aplicação de Proxy para funcionalidade, ao invés de economia, ocorre em frameworks de “remoting”.
Como uma referência direta à memória de outro processo é impossível, o programa local faz referência a um objeto Proxy ao invés; e o Proxy oculta a solução para o problema de comunicação entre processos.

Qualquer objeto que está para um sistema externo – como um conector de banco de dados – pode ser considerado um Proxy do sistema externo no programa local.
Note que “proxy” é inglês para “procurador” – uma pessoa legalmente habilitada a agir em nome de outra.

O que não consigo compreender é como você disse o Proxy é um procurador, porém nos exemplos que eu li, entendi que o proxy esta agindo como um intermediário em um determinado momento assim chamando uma classe para executar algo, como no exemplo a cima onde a classe proxy se não me engano é utilizada para realizar a consulta no banco me corrijam se estiver errado, mas qual a necessidade disso ?

xjunior

Na verdade, no seu exemplo o proxy é usado como um intermediário entre a consulta com o banco de dados, pois observe que na sua interface existe os métodos que devem ser implementados, e na sua classe ProxyPessoa implementa os métodos em comum com a classe PessoaImpl, realizando assim um proxy encapsula o PessoaImpl e vc usa na verdade o proxy.

Estude também os outros padrões estruturais, pois a filosofia deles são bem parecidas, e outros que são muito usados são pattern adpater e o decorator.

A

xjunior:
Na verdade, no seu exemplo o proxy é usado como um intermediário entre a consulta com o banco de dados, pois observe que na sua interface existe os métodos que devem ser implementados, e na sua classe ProxyPessoa implementa os métodos em comum com a classe PessoaImpl, realizando assim um proxy encapsula o PessoaImpl e vc usa na verdade o proxy.

Estude também os outros padrões estruturais, pois a filosofia deles são bem parecidas, e outros que são muito usados são pattern adpater e o decorator.

mas xjunior o que não compreendo é o por que de usar isso, pois nunca implementei isso é um trabalho que estou fazendo então para realizar isso que esta acontecendo eu utilizo observer e oservable no mvc então o por que devo encapsular a classe PessoaImpl para realizar a consulta?

xjunior

Bom amigo, lembre-se que o observer é um padrão comportamental e não estrutural, visite este link que irá dar uma visão semântica sobre os design patterns e como utilizá-los, não tem implementação, mas é excelente fonte para vc saber o que é e como implementar.

http://www.pg.cefetpr.br/coinf/simone/patterns/

xjunior

O objetivo na lata do proxy é transformar algo complexo em simples e lembra do proxy em servidor, para que ele serve???

Este design pattern nao possui filosofia diferente, e sim um proxy na empresa (lembrando do servidor…) guarda cache das páginas acessadas, não é? Implementa segurança, e faz com que o acesso seja “mais rápido”…

O design pattern proxy é para fazer o acesso ser mais rápido em algo custoso… Ter um intermediário entre o complexo e a sua implementação, ok?

ViniGodoy

acidburn:
Tenho uma classe que busca no banco uma imagem muito grande, então crio um proxy desta classe assim posso Instanciar o objeto real pela proxy somente quando necessário asim não alocando a memória antecipadamente
seria isso?

É exatamente isso. Um proxy pode controlar acesso por diversos motivos:

  1. Lazy loading (exemplo que você deu);
  2. Controle ou restrições de acesso;
  3. Sincronização
  4. Caching (exemplo dado pelo xjunior);

O proxy não adiciona nenhuma funcionalidade aparente a quem usa a classe. É diferente do decorator, que agrega uma função. Diferenciar um do outro as vezes é bastante difícil.

As collections do Java fornecem dois tipos de proxy. Um deles para tornar a collection read-only e outro para fornecer acesso sincronizado.

List<String> lista = new ArrayList<String>(); List<String> listaSincronizada = Collections.synchronizedList(lista); List<String> listaReadOnly = Collections.unmodifiableList(lista);

Não confundir esse proxy com o proxy dinâmico do Java, a classe Proxy.

A

xjunior:
Bom amigo, lembre-se que o observer é um padrão comportamental e não estrutural, visite este link que irá dar uma visão semântica sobre os design patterns e como utilizá-los, não tem implementação, mas é excelente fonte para vc saber o que é e como implementar.

http://www.pg.cefetpr.br/coinf/simone/patterns/

não consigo acessar o proxy esta com erro no link que você sugeriu

ViniGodoy

Ah, outro detalhe. Não confudir:

  1. O design pattern com a classe Proxy;
  2. O design pattern com um servidor de Proxy;

O proxy também se comporta como a classe que você quer acessar. O usuário pode nem saber que está lidando com um proxy. Note no exemplo acima, que nos 3 casos você acaba com um List<String> na mão. No caso da sua classe de imagem, o proxy e a imagem deveriam implementar uma interface comum, Image.

A classe ficaria assim:

//Interface comum
public interface Image
{
   void draw(Graphics2D g);
}

//Sua classe de negócio
public class MyImage extends Image
{
    private BufferedImage image;
    public MyImage(BufferedImage img) {
         image = img;
    }

    public void draw(Graphics2D g) {
       g.drawImage(image, 0,0, null);
    }        
}

//Proxy
public class LazyImageProxy implements Image {
    private MyImage image = null;
    private File file; 

    public LazyImageProxy(File file) {
        this.file = file;
    }

    private Image lazyImage() {
        if (image == null) 
            image = new MyImage(ImageIO.read(new File("C:/ImagemGrandeEPesada.tiff")));
        return image;
    }

    public void draw(Graphics2D g) {
       lazyImage.draw(g);
    }
}

Note que alguns poderiam argumentar que aquele proxy é, na verdade, um decorator, já que ele acrescenta a funcionalidade de lazy-loading. Isso é restrição de acesso ou funcionalidade extra? Depende do ponto de vista… em todo caso a implementação seria idêntica e, na minha opinião, discutir isso é discutir o sexo dos anjos.

A

Por qual motivo a terceira pessoa não sera chamada, vejo que o modelo que esta sendo utilizado esta diferente é por isso?

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 System.out.println("Id da 3ª - " + pessoas.get(2).getId());//pode imprimir o ID do objeto, e o proxy nao será inicializado.

P

acidburn:
pedro.lamarao:
Um bom exemplo de aplicação de Proxy para funcionalidade, ao invés de economia, ocorre em frameworks de “remoting”.
Como uma referência direta à memória de outro processo é impossível, o programa local faz referência a um objeto Proxy ao invés; e o Proxy oculta a solução para o problema de comunicação entre processos.

Qualquer objeto que está para um sistema externo – como um conector de banco de dados – pode ser considerado um Proxy do sistema externo no programa local.
Note que “proxy” é inglês para “procurador” – uma pessoa legalmente habilitada a agir em nome de outra.

O que não consigo compreender é como você disse o Proxy é um procurador, porém nos exemplos que eu li, entendi que o proxy esta agindo como um intermediário em um determinado momento assim chamando uma classe para executar algo, como no exemplo a cima onde a classe proxy se não me engano é utilizada para realizar a consulta no banco me corrijam se estiver errado, mas qual a necessidade disso ?

Talvez a questão não seja sobre necessidade, mas sobre utilidade.
É claro que um idéia de um Proxy puro parece inútil – se ele é idêntico ao objeto original, porque não acessar o objeto original logo de uma vez?
O Proxy parece mais útil quando ele oculta alguma regra adicional que seja útil.
No seu exemplo, essa regra adicional parece ser um cache de dados recuperados do banco – de modo que os acessos subsequentes são mais econômicos.

ViniGodoy

No proxy que você implementou, é pq o método getId() não aciona a busca. Como o id é passado no construtor e o proxy o armazena internamente, não tem pq fazer busca se você só quiser saber o id. Se fizer pessoa.get(2).getNome() aí sim, a busca será acionada.

A

No proxy que você implementou, é pq o método getId() não aciona a busca. Como o id é passado no construtor e o proxy o armazena internamente, não tem pq fazer busca se você só quiser saber o id. Se fizer pessoa.get(2).getNome() aí sim, a busca será acionada.

a então é isso mesmo

A

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 System.out.println("Id da 3ª - " + pessoas.get(2).getId());//pode imprimir o ID do objeto, e o proxy nao será inicializado.

Por que na busca da segunda pessoa ele alega estar no cache, é por que o objeto proxy vai estar carregado com dados?

ViniGodoy

Sim. E num segundo getNome() ele não buscará nada no banco.

xjunior

Isto mesmo, acidbun, então ele não buscará pois fará o cache desta busca…

Criado 8 de abril de 2010
Ultima resposta 8 de abr. de 2010
Respostas 25
Participantes 4