Duvidas Pattern Proxy

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?

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?

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

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?

[quote=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?[/quote]

???

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

O exemplo que estou tentando intender:

[code]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 pessoas = new ArrayList();

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

    }
    }
    [/code]

exemplo tirado do DevMedia postado por Ricardo Rodrigues

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.

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

Valeu pela dica, esta editado

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.

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?

[quote=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.[/quote]

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 ?

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.

[quote=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.[/quote]

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?

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/

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?

[quote=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?[/quote]

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

[quote=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/[/quote]

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

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.

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.