Pular para o conteúdo
GoF Padrões de Projeto Estruturais
Estrutural escopo de objeto
GoF, p. 207 também chamado de Surrogate

Procurador

Proxy

Um substituto com a mesma cara, que controla o acesso ao objeto real.

Complexidade média Frequência de uso moderada
Intençãocomo o livro define

Fornecer um substituto ou marcador de outro objeto para controlar o acesso a ele.

Analogiauma imagem do mundo real

O cartão de crédito

O cartão representa o dinheiro na sua conta. Onde o dinheiro é aceito, ele também é — mesma “interface”. Mas ele acrescenta controle: verifica limite, exige senha, registra a transação e evita que você carregue a quantia física. O comerciante não sabe nem se importa com a diferença.

O problema

Você quer executar algo antes ou depois de acessar um objeto — carregá-lo tarde, verificar permissão, cachear, contar acessos, logar — mas não pode ou não quer alterar a classe dele, e nem espalhar essa lógica em todos os chamadores.

A solução

Crie uma classe com a MESMA interface do objeto real. O cliente recebe o proxy sem perceber; o proxy faz o trabalho extra e delega ao objeto real quando (e se) for o caso.

Sintomascomo reconhecer no seu código
  • Verificação de permissão duplicada em todos os métodos de um serviço.
  • Objetos caros carregados na inicialização e quase nunca usados.

Estrutura

delega quando precisaClient«interface»Biblioteca+ baixar(id)BibliotecaComCache- real- cacheBibliotecaReal+ baixar(id)
Fig. 12 — Proxy herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
ServiceInterface
Interface compartilhada por proxy e serviço real.
Service
A classe que faz o trabalho de verdade.
Proxy
Guarda a referência ao serviço, controla acesso e delega.
Client
Programa contra a interface; não sabe se fala com proxy ou serviço.
Variações
  • Virtual — adia a criação de um objeto caro até o primeiro uso real.
  • Remoto — representa localmente um objeto que vive em outro processo/máquina.
  • De proteção — verifica permissões antes de deixar passar.
  • De log / smart reference — registra acessos, conta referências, libera recursos.
  • De cache — guarda resultados de chamadas repetidas.

Implementação

Listagem 12 Proxy virtual + de proteção sobre um repositório de documentos
class RepositorioDocumentos {
  buscar(id) { throw new Error('abstrato'); }
}

// ── Serviço real: caro de instanciar ──────────────────
class RepositorioReal extends RepositorioDocumentos {
  constructor() {
    super();
    console.log('🐢 abrindo conexão + carregando índice (2s)…');   // custo alto
    this.docs = new Map([[1, { id: 1, titulo: 'Contrato', sigilo: 'alto' }]]);
  }
  buscar(id) { console.log(`💾 lendo do disco: ${id}`); return this.docs.get(id); }
}

// ── Proxy: virtual (lazy) + proteção + cache ──────────
class RepositorioProtegido extends RepositorioDocumentos {
  #real = null;                 // ainda NÃO existe
  #cache = new Map();
  constructor(usuario) { super(); this.usuario = usuario; }

  #obterReal() {
    // Proxy VIRTUAL: só paga os 2 segundos se alguém realmente usar.
    if (!this.#real) this.#real = new RepositorioReal();
    return this.#real;
  }

  buscar(id) {
    // Proxy de PROTEÇÃO
    if (this.usuario.papel !== 'admin') throw new Error('🚫 acesso negado');
    // Proxy de CACHE
    if (this.#cache.has(id)) { console.log(`⚡ cache: ${id}`); return this.#cache.get(id); }
    const doc = this.#obterReal().buscar(id);
    this.#cache.set(id, doc);
    return doc;
  }
}

// Nenhum objeto real foi criado ainda — construir o proxy é instantâneo.
const repo = new RepositorioProtegido({ papel: 'admin' });
repo.buscar(1);   // 🐢 constrói agora, 💾 lê do disco
repo.buscar(1);   // ⚡ cache

const visitante = new RepositorioProtegido({ papel: 'leitor' });
try { visitante.buscar(1); } catch (e) { console.log(e.message); }  // 🚫 — e nada foi carregado
Na práticaonde ele já existe
  • java.lang.reflect.Proxy e proxies dinâmicos de ORMs (lazy loading do Hibernate)
  • O objeto `Proxy` nativo do JavaScript
  • Service mesh / API gateway — proxies em nível de infraestrutura

Consequências

A favor
  • Controla o objeto de serviço sem que o cliente saiba.
  • Gerencia o ciclo de vida do objeto real (criação tardia, liberação).
  • Funciona mesmo com o serviço indisponível ou remoto.
  • Novos proxies entram sem alterar clientes nem o serviço (Aberto/Fechado).
Contra
  • Mais uma camada — resposta pode ficar mais lenta.
  • Mais classes para manter.
Use quando
  • Carregamento tardio de objetos pesados (proxy virtual).
  • Controle de acesso por permissão (proxy de proteção).
  • Objeto remoto representado localmente (proxy remoto).
  • Log, métricas ou cache transparentes.
Evite quando
  • Você quer ADICIONAR comportamento combinável escolhido pelo cliente — isso é Decorator.

Relações com outros padrões

parecido / fácil de confundir
Decorator
Mesma estrutura. Proxy geralmente CRIA e gerencia o objeto real sozinho; o Decorator recebe pronto do cliente e o cliente escolhe empilhar.
Adapter
Adapter troca a interface; Proxy mantém.
Facade
Facade tem interface própria e simplificada; Proxy tem a mesma interface do alvo.
costuma andar junto
Flyweight
Proxy pode ser o ponto onde o objeto compartilhado é resolvido.

Verificação

Questãoa resposta está marcada

Proxy e Decorator têm estrutura idêntica. Qual pista prática melhor os distingue?

  1. Quem controla o objeto envolvido: o Proxy normalmente o cria e gerencia sozinho; o Decorator recebe pronto e serve para empilhar comportamento escolhido pelo cliente
  2. Proxy só funciona com objetos remotos
  3. Decorator não pode ser aninhado
  4. Proxy é sempre mais rápido

A intenção decide: controlar acesso e ciclo de vida (Proxy) versus enriquecer comportamento de forma combinável (Decorator).