Diferenças entre Proxy e Padrão Decorador


136

Você pode dar uma boa explicação sobre qual é a diferença entre Proxy e Decorator ?

A principal diferença que vejo é que, quando assumimos que o Proxy usa composição e o Decorator usa agregação , parece claro que, usando vários Decorators (um ou mais), você pode modificar / adicionar funcionalidades à instância pré-existente (decorar), enquanto O proxy possui uma instância interna própria da classe em proxy e delega a ela adicionando alguns recursos adicionais (comportamento do proxy).

A pergunta é: o proxy criado com agregação ainda é um proxy ou um decorador ? É permitido (por definição nos padrões GoF) criar Proxy com agregação?


2

5
De onde você tirou a ideia de que o Proxy usa composição e o Decorator usa agregação?
cperkins

1
@CPerkins veja meu comentário para a resposta de Rahul Tripathi.
Łukasz Rzeszotarski 04/04

1
E também decorador ( patterns.cs.up.ac.za/examples/ch2/decorator-theory.cs ) - obviamente agregação, proxy ( patterns.cs.up.ac.za/examples/ch2/proxy-theory.cs ) - obviamente composição.
Hyankov 13/03/16

Respostas:


16

Aqui está a citação direta do GoF (página 216).

Embora os decoradores possam ter implementações semelhantes às proxies, os decoradores têm uma finalidade diferente. Um decorador adiciona uma ou mais responsabilidades a um objeto, enquanto um proxy controla o acesso a um objeto.

Os proxies variam no grau em que são implementados como um decorador. Um proxy de proteção pode ser implementado exatamente como um decorador. Por outro lado, um proxy remoto não conterá uma referência direta ao assunto real, mas apenas uma referência indireta, como "ID do host e endereço local no host". Um proxy virtual começará com uma referência indireta, como um nome de arquivo, mas eventualmente obterá e usará uma referência direta.

Respostas populares indicam que um Proxy conhece o tipo concreto de seu delegado. A partir desta citação, podemos ver que nem sempre é verdade.

A diferença entre o Proxy e o Decorator de acordo com o GoF é que o Proxy restringe o cliente. Decorador não. O proxy pode restringir o que um cliente faz controlando o acesso à funcionalidade; ou pode restringir o que um cliente sabe executando ações invisíveis e desconhecidas para o cliente. O Decorator faz o oposto: ele aprimora o que seu delegado faz de uma maneira que é visível para os clientes.

Podemos dizer que o Proxy é uma caixa preta, enquanto o Decorator é uma caixa branca.

O relacionamento de composição entre o wrapper e o delegado é o relacionamento errado no qual o Proxy e o Decorator são contrastados, porque a composição é o recurso que esses dois padrões têm em comum. O relacionamento entre wrapper e cliente é o que diferencia esses dois padrões.

  • Decorator informa e capacita seu cliente.
  • O proxy restringe e desimpede seu cliente.

113

A diferença real não é propriedade (composição versus agregação), mas informações de tipo.

Um decorador sempre recebe seu delegado. Um Proxy pode criar ele mesmo, ou ele pode ser injetado.

Mas um Proxy sempre conhece o tipo (mais) específico do delegado. Em outras palavras, o Proxy e seu representante terão o mesmo tipo de base, mas o Proxy aponta para algum tipo derivado. Um Decorador aponta para seu próprio tipo de base. Portanto, a diferença está nas informações em tempo de compilação sobre o tipo de delegado.

Em um idioma dinâmico, se o delegado for injetado e tiver a mesma interface, não haverá diferença.

A resposta para sua pergunta é sim".


2
“Mas um Proxy sempre conhece o tipo (mais) específico de delegado.” Não acho que seja verdade. Imagine proxy remoto. O mecanismo de proxy não precisa conhecer nenhum detalhe do objeto remoto. O sistema remoto registra o objeto com a interface especificada. E o proxy local expõe a mesma interface.
21415 Alexey

3
Tive uma aula sobre isso na Amazon com um professor visitante que conhecia as coisas dele. Há uma diferença entre o uso de um executável "proxy" (por exemplo, com um serviço da web) e o Padrão de Design do Proxy. As UMLs do padrão Proxy e do padrão Decorator podem ser diferentes. Mas nada impede que um Proxy tenha a mesma API que seu representante. O Decorator é um subconjunto estrito do Proxy, mas um Decorator ainda pode ser chamado de Proxy, dependendo da garantia da API subjacente ser a mesma.
cdunn2001

85

O Decorator Pattern se concentra em adicionar funções dinamicamente a um objeto, enquanto o Proxy Pattern se concentra em controlar o acesso a um objeto.

EDITAR:-

A relação entre um Proxy e o assunto real geralmente é definida em tempo de compilação, o Proxy o instancia de alguma maneira, enquanto o Decorator é atribuído ao sujeito em tempo de execução, conhecendo apenas a interface do sujeito.


5
Um proxy ainda pode ser usado para adicionar funcionalidade. Pense nos proxies da AOP.
Sotirios Delimanolis

5
Concordo plenamente, senhor. Gostaria de converter isso em outras palavras, o que eu quis dizer com Proxy Pattern, a classe proxy pode ocultar as informações detalhadas de um objeto de seu cliente. Portanto, ao usar o Proxy Pattern, geralmente criamos uma instância de abject dentro da classe de proxy. E ao usar o Decorator Pattern, normalmente passamos o objeto original como parâmetro para o construtor do decorador.
Rahul Tripathi

Nesse caso, quando a instância está 'oculta' no proxy, a diferença é clara para mim (como escrevi), no entanto, acho que muitas vezes as pessoas chamam de classes proxy que pegam o objeto proxy que foi passado como parâmetro construtor. Nesse caso, a diferença de adicionar novas funcionalidades ou controlar é (muito) pequena para mim.
Łukasz Rzeszotarski

5
O relacionamento entre um Proxy e o assunto real geralmente é definido em tempo de compilação; o Proxy o instancia de alguma forma, enquanto o Decorator ou o Adaptador são atribuídos ao sujeito em tempo de execução, conhecendo apenas a interface do sujeito. Espero que faça sentido !!! :)
Rahul Tripathi

1
Você pode adicionar esta linha à sua resposta.
Łukasz Rzeszotarski

49

O Decorator obtém referência para objetos decorados (geralmente através do construtor), enquanto o Proxy é responsável por fazer isso sozinho.

O proxy pode não instanciar o objeto de quebra automática (como os ORMs para impedir o acesso desnecessário ao banco de dados se os campos / getters de objetos não forem usados) enquanto o Decorator sempre mantém o link para a instância real quebrada.

Proxy geralmente usado por estruturas para adicionar segurança ou armazenamento em cache / descanso e construído por estrutura (não pelo próprio desenvolvedor regular).

O Decorator geralmente é usado para adicionar novo comportamento às classes antigas ou herdadas pelo próprio desenvolvedor, com base na interface e não na classe real (para que ele funcione em uma ampla variedade de instâncias de interface, o Proxy é uma classe concreta).


22

Principais diferenças:

  1. O proxy fornece a mesma interface. O Decorator fornece uma interface aprimorada.
  2. O Decorator e o Proxy têm finalidades diferentes, mas estruturas semelhantes. Ambos descrevem como fornecer um nível de indireção para outro objeto, e as implementações mantêm uma referência ao objeto para o qual encaminham solicitações.
  3. O Decorator pode ser visto como um composto degenerado com apenas um componente. No entanto, um Decorator adiciona responsabilidades adicionais - não se destina à agregação de objetos.
  4. Decorator suporta composição recursiva
  5. A classe Decorator declara um relacionamento de composição com a interface LCD (denominador de classe mais baixa) e esse membro de dados é inicializado em seu construtor.
  6. Use o Proxy para inicialização lenta, melhoria de desempenho, armazenando em cache o objeto e controlando o acesso ao cliente / chamador

O artigo de criação de fontes cita as semelhanças e diferenças de maneira excelente.

Perguntas / links relacionados ao SE:

Quando usar o padrão do decorador?

Qual é a diferença exata entre os padrões de adaptador e proxy?


3

O proxy e o decorador diferem em finalidade e em que se concentram na implementação interna. O proxy é para usar um objeto remoto, entre processos ou entre redes como se fosse um objeto local. O Decorator é para adicionar novo comportamento à interface original.

Embora os dois padrões tenham estrutura semelhante, a maior parte da complexidade do Proxy reside em garantir a comunicação adequada com o objeto de origem. O Decorator, por outro lado, concentra-se na implementação do comportamento adicionado.


O que você está dizendo diferente das outras 4 respostas já aqui?
Stephen Rauch

Não sei se está tudo lá. Eu apenas senti vontade de gritar depois de ler as respostas anteriores.
James Lin

1

Demorou um pouco para descobrir essa resposta e o que ela realmente significa. Alguns exemplos devem torná-lo mais claro.

Proxy primeiro:

public interface Authorization {
    String getToken();
} 

E:

// goes to the DB and gets a token for example
public class DBAuthorization implements Authorization {
    @Override
    public String getToken() {
        return "DB-Token";
    }
}

E há um interlocutor disso Authorization, bastante idiota:

class Caller {
    void authenticatedUserAction(Authorization authorization) {
        System.out.println("doing some action with : " + authorization.getToken());
    }
}

Nada incomum até agora, certo? Obtenha um token de um determinado serviço, use esse token. Agora vem mais um requisito para a imagem, adicione log: significando registrar o token sempre. É simples para este caso, basta criar um Proxy:

public class LoggingDBAuthorization implements Authorization {

    private final DBAuthorization dbAuthorization = new DBAuthorization();

    @Override
    public String getToken() {
        String token = dbAuthorization.getToken();
        System.out.println("Got token : " + token);
        return token;
    }
}

Como usaríamos isso?

public static void main(String[] args) {
    LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();

    Caller caller = new Caller();
    caller.authenticatedUserAction(loggingDBAuthorization);
}

Observe que LoggingDBAuthorization contém uma instância de DBAuthorization. Ambos LoggingDBAuthorizatione DBAuthorization implementar Authorization .

  • Um proxy realizará alguma implementação concreta ( DBAuthorization) da interface base ( Authorization). Em outras palavras, um Proxy sabe exatamente o que está sendo procurado.

Decorator:

Começa praticamente da mesma forma que Proxy, com uma interface:

public interface JobSeeker {
    int interviewScore();
}

e uma implementação do mesmo:

class Newbie implements JobSeeker  {
    @Override
    public int interviewScore() {
        return 10;
    }
}

E agora queremos adicionar um candidato mais experiente, que adicione a pontuação da entrevista e a pontuação do outro JobSeeker:

@RequiredArgsConstructor 
public class TwoYearsInTheIndustry implements JobSeeker {

    private final JobSeeker jobSeeker;

    @Override
    public int interviewScore() {
        return jobSeeker.interviewScore() + 20;
    } 
}

Observe como eu disse isso, mais o de outro JobSeeker , não Newbie . A Decoratornão sabe exatamente o que está decorando, conhece apenas o contrato dessa instância decorada (sabe sobre JobSeeker). Observe aqui que isso é diferente de a Proxy; que, ao contrário, sabe exatamente o que está decorando.

Você pode questionar se há realmente alguma diferença entre os dois padrões de design nesse caso? E se tentássemos escrever o Decoratorcomo a Proxy?

public class TwoYearsInTheIndustry implements JobSeeker {

    private final Newbie newbie = new Newbie();

    @Override
    public int interviewScore() {
        return newbie.interviewScore() + 20;
    }
}

Essa é definitivamente uma opção e destaca o quão próximos esses padrões são; eles ainda são destinados a diferentes cenários, conforme explicado nas outras respostas.


1

O proxy fornece a mesma interface para o objeto agrupado , o Decorator fornece uma interface aprimorada, e o Proxy geralmente gerencia o ciclo de vida de seu objeto de serviço por conta própria, enquanto a composição dos Decoradores é sempre controlada pelo cliente.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.