Eu estava olhando para o Proxy Pattern, e para mim parece muito com os padrões Decorator, Adapter e Bridge. Estou entendendo mal alguma coisa? Qual é a diferença? Por que eu usaria o padrão Proxy versus os outros? Como você os usou no passado em projetos do mundo real?
design-patterns
decorator
bridge
proxy-pattern
Charles Graham
fonte
fonte
Respostas:
Proxy, Decorator, Adapter e Bridge são variações de "quebra" de uma classe. Mas seus usos são diferentes.
O proxy pode ser usado quando você deseja instanciar preguiçosamente um objeto, ocultar o fato de estar chamando um serviço remoto ou controlar o acesso ao objeto.
O Decorator também é chamado de "Proxy Inteligente". Isso é usado quando você deseja adicionar funcionalidade a um objeto, mas não estendendo o tipo desse objeto. Isso permite que você faça isso em tempo de execução.
O adaptador é usado quando você possui uma interface abstrata e deseja mapear essa interface para outro objeto que tenha função funcional semelhante, mas uma interface diferente.
Bridge é muito semelhante ao Adapter, mas chamamos de Bridge quando você define a interface abstrata e a implementação subjacente. Ou seja, você não está se adaptando a algum código herdado ou de terceiros, você é o designer de todo o código, mas precisa ser capaz de trocar implementações diferentes.
Fachada é uma interface de nível superior (leia-se: mais simples) para um subsistema de uma ou mais classes. Suponha que você tenha um conceito complexo que exija vários objetos para representar. Fazer alterações nesse conjunto de objetos é confuso, porque você nem sempre sabe qual objeto tem o método que precisa chamar. É o momento de escrever uma Fachada que fornece métodos de alto nível para todas as operações complexas que você pode fazer na coleção de objetos. Exemplo: um Modelo de Domínio para uma seção de escola, com métodos como
countStudents()
,reportAttendance()
,assignSubstituteTeacher()
e assim por diante.fonte
Como a resposta de Bill diz, seus casos de uso são diferentes .
O mesmo acontece com as estruturas deles.
Proxy e Decorator têm a mesma interface que seus tipos agrupados, mas o proxy cria uma instância sob o capô, enquanto o decorador cria uma instância no construtor.
O Adapter e o Facade têm uma interface diferente da que eles envolvem. Mas o adaptador deriva de uma interface existente, enquanto a fachada cria uma nova interface.
Ponte e adaptador apontam para um tipo existente. Mas a ponte apontará para um tipo abstrato e o adaptador poderá apontar para um tipo concreto. A ponte permitirá que você emparelhe a implementação em tempo de execução, enquanto o adaptador normalmente não.
fonte
Minha opinião sobre o assunto.
Todos os quatro padrões têm muito em comum, todos os quatro são chamados informalmente de invólucros ou padrões de invólucro. Todos usam composição, agrupando o assunto e delegando a execução ao assunto em algum momento, mapeando uma chamada de método para outra. Eles poupam ao cliente a necessidade de construir um objeto diferente e copiar todos os dados relevantes. Se usados com sabedoria, eles economizam memória e processador.
Ao promover o acoplamento flexível, eles tornam o código, uma vez estável, menos exposto a mudanças inevitáveis e mais legível para outros desenvolvedores.
Adaptador
O adaptador adapta o assunto (adaptado) a uma interface diferente. Dessa forma, podemos adicionar objetos a uma coleção de tipos nominalmente diferentes.
O adaptador expõe apenas métodos relevantes ao cliente, pode restringir todos os outros, revelando intenções de uso para contextos específicos, como adaptar a biblioteca externa, fazer com que pareça menos geral e mais focado nas necessidades de nossos aplicativos. Os adaptadores aumentam a legibilidade e a auto descrição de nosso código.
Os adaptadores protegem uma equipe do código volátil de outras equipes; uma ferramenta de salvador de vidas ao lidar com equipes offshore ;-)
O objetivo menos mencionado é impedir que a classe de assunto exceda as anotações. Com tantas estruturas baseadas em anotações, isso se torna um uso mais importante do que nunca.
O adaptador ajuda a contornar a limitação de Java de apenas uma herança. Ele pode combinar vários adaptados em um envelope, dando a impressão de herança múltipla.
Em termos de código, o adaptador é "fino". Ele não deve adicionar muito código à classe adaptee, além de simplesmente chamar o método adaptee e ocasionais conversões de dados necessárias para fazer essas chamadas.
Não há muitos bons exemplos de adaptadores no JDK ou nas bibliotecas básicas. Os desenvolvedores de aplicativos criam adaptadores para adaptar bibliotecas a interfaces específicas de aplicativos.
Decorador
O Decorator não apenas delega, não apenas mapeia um método para outro, mas também modifica o comportamento de alguns métodos de assunto, pode decidir não chamar o método de assunto, delegar para um objeto diferente, um objeto auxiliar.
Decoradores normalmente adicionam funcionalidade (transparente) a objetos quebrados, como log, criptografia, formatação ou compactação ao assunto. Essa nova funcionalidade pode trazer muitos códigos novos. Portanto, os decoradores geralmente são muito mais "gordos" que os adaptadores.
O decorador deve ser uma subclasse da interface do sujeito. Eles podem ser usados de forma transparente em vez de seus assuntos. Consulte BufferedOutputStream, ainda é OutputStream e pode ser usado como tal. Essa é uma grande diferença técnica dos adaptadores.
Exemplos de livros de texto de toda a família de decoradores estão prontamente no JDK - o Java IO. Todas as classes, como BufferedOutputStream , FilterOutputStream e ObjectOutputStream, são decoradoras de OutputStream . Eles podem ser em camadas de cebola, onde um decorador é decorado novamente, adicionando mais funcionalidade.
Proxy
O proxy não é um wrapper típico. O objeto agrupado, o assunto do proxy, ainda não pode existir no momento da criação do proxy. O proxy geralmente o cria internamente. Pode ser um objeto pesado criado sob demanda ou é um objeto remoto em JVM diferente ou em um nó de rede diferente e até mesmo um objeto não Java, um componente no código nativo. Ele não precisa envolver ou delegar a outro objeto.
Os exemplos mais comuns são proxies remotos, inicializadores de objetos pesados e proxies de acesso.
Proxy Remoto - o assunto está no servidor remoto, em JVM diferente ou mesmo em um sistema não Java. O proxy converte chamadas de método para chamadas RMI / REST / SOAP ou o que for necessário, protegendo o cliente da exposição à tecnologia subjacente.
Lazy Load Proxy - inicialize totalmente o objeto apenas no primeiro uso ou no primeiro uso intensivo.
Proxy de acesso - controle o acesso ao assunto.
Fachada
Fachada está intimamente associada ao Princípio do Menos Conhecimento do Projeto (Lei de Demeter). Fachada é muito semelhante ao adaptador. Ambos envolvem, ambos mapeiam um objeto para outro, mas diferem na intenção. Fachada nivela a estrutura complexa de um assunto, gráfico de objetos complexos, simplificando o acesso a uma estrutura complexa.
Fachada envolve uma estrutura complexa, fornecendo uma interface plana para ela. Isso evita que o objeto cliente seja exposto a relações internas na estrutura do sujeito, promovendo assim um acoplamento flexível.
Ponte
Variante mais complexa do padrão do adaptador, onde não apenas a implementação varia, mas também a abstração. Acrescenta mais um indireto à delegação. A delegação extra é a ponte. Ele desacopla o adaptador até da interface de adaptação. Aumenta a complexidade mais do que qualquer outro padrão de empacotamento, portanto, aplique com cuidado.
Diferenças nos construtores
Diferenças de padrão também são óbvias quando se olha para seus construtores.
O proxy não está quebrando um objeto existente. Não há assunto no construtor.
O Decorator e o Adapter envolvem o objeto já existente, e isso geralmente é
fornecido no construtor.
O construtor Facade pega o elemento raiz de um gráfico de objeto inteiro, caso contrário, parece o mesmo que o Adapter.
Exemplo da vida real - Adaptador Marshalling JAXB . O objetivo deste adaptador é mapear uma classe simples e plana para uma estrutura mais complexa requerida externamente e evitar a classe de assunto "poluente" com anotações excessivas.
fonte
Há muita sobreposição em muitos dos padrões GoF. Todos eles são construídos com base no poder do polimorfismo e, às vezes, diferem apenas na intenção. (estratégia vs. estado)
Minha compreensão dos padrões aumentou 100 vezes depois de ler Head First Design Patterns .
Eu recomendo!
fonte
Todas as boas respostas de especialistas já explicaram o que significa cada padrão.
Vou decorar pontos-chave.
Decorador:
por exemplo (com encadeamento):
java.io
classes de pacotes relacionadas aInputStream
&OutputStream
interfacesProxy:
por exemplo:
java.rmi
classes de pacotes.Adaptador:
por exemplo
java.io.InputStreamReader
(InputStream
retorna aReader
)Ponte:
por exemplo, classes de coleção em
java.util
.List
implementado porArrayList
.Notas principais:
Dê uma olhada nas ótimas perguntas / artigos do SE sobre exemplos de vários padrões de design
Quando usar o padrão do decorador?
Quando você usa o padrão de ponte? Como é diferente do padrão do adaptador?
Diferenças entre Proxy e Padrão Decorador
fonte
Eles são bastante semelhantes, e as linhas entre eles são bastante cinzas. Sugiro que você leia as entradas Padrão de proxy e Padrão de decorador no wiki do c2.
As entradas e discussões são bastante extensas e também possuem links para outros artigos relevantes. A propósito, o wiki c2 é excelente quando se pergunta sobre as nuances entre os diferentes padrões.
Para resumir as entradas c2, eu diria que um decorador adiciona / altera o comportamento, mas um proxy tem mais a ver com controle de acesso (instanciação lenta, acesso remoto, segurança etc.). Mas, como eu disse, as linhas entre elas são cinza e vejo referências a proxies que podem ser facilmente visualizados como decoradores e vice-versa.
fonte
Todos os quatro padrões envolvem a quebra de objetos / classes internos com os externos, portanto, são estruturalmente muito semelhantes. Eu descreveria a diferença com o objetivo:
E pela variação da interface entre objetos internos e externos:
fonte
Citação de Head First Design Patterns
As definições pertencem ao livro. Exemplos me pertence.
Decorador - Não altera a interface, mas agrega responsabilidade. Suponha que você tenha uma interface de carro. Ao implementar isso para diferentes modelos de carro (s, sv, sl), você pode precisar adicionar mais responsabilidades para alguns modelos. Como tem teto solar, airbag etc.
Adaptador - Converte uma interface para outra. Você tem uma interface de carro e gostaria que ele agisse como um jipe. Então você pega o carro, modifica e vira um jipe. Uma vez que não é um jipe de verdade. Mas age como um jipe.
Fachada - simplifica a interface. Suponha que você tenha interfaces de carro, avião, navio. Na verdade, tudo o que você precisa é de uma classe que envie pessoas de um local para outro. Você quer que a fachada decida qual veículo usar. Então você coleta todas essas referências de interface sob um guarda-chuva e deixa que ele decida / delegue para simplificar.
Head First: "Uma fachada não apenas simplifica uma interface, mas desacopla um cliente de um subsistema de componentes. Fachadas e adaptadores podem agrupar várias classes, mas a intenção de uma fachada é simplificar, enquanto o adaptador é converter a interface em algo diferente. "
fonte
Eu o uso com bastante frequência ao consumir serviços da web. O Proxy Pattern provavelmente deve ser renomeado para algo mais pragmático, como 'Wrapper Pattern ". Também tenho uma biblioteca que é um Proxy para o MS Excel. Torna muito fácil automatizar o Excel, sem ter que se preocupar com detalhes de plano de fundo, como o que versão está instalada (se houver).
fonte
Falando na implementação detalhada, encontro uma diferença entre Proxy e Decorator, Adapter, Facade ... Na implementação comum desses padrões, há um objeto de destino envolvido por um objeto de fechamento. O cliente usa o objeto anexo em vez do objeto de destino. E o objeto de destino realmente desempenha um papel importante em alguns métodos de inclusão de objetos.
No entanto, no caso do Proxy, o objeto envolvente pode executar alguns métodos por si só, apenas inicializa o objeto de destino quando o cliente chama alguns métodos dos quais ele precisa participar. Essa é uma inicialização lenta. No caso de outros padrões, o objeto anexo é praticamente baseado no objeto de destino. Portanto, o objeto de destino é sempre inicializado junto com o objeto envolvente nos construtores / setters.
Outra coisa, um proxy faz exatamente o que um destino faz, enquanto outros padrões adicionam mais funcionalidade ao destino.
fonte
Gostaria de adicionar exemplos à resposta de Bill Karwing (o que é ótimo). Eu também adiciono algumas diferenças importantes de implementação, que sinto que estão faltando
As partes citadas são da resposta de [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)
ProxyClass e ObjectClass com proxy, devem implementar a mesma interface, para que sejam intercambiáveis
Exemplo - objeto caro de proxy
DecoratorClass deve (poderia) implementar uma interface estendida de ObjectClass. Portanto, o ObjectClass pode ser substituído pelo DecoratorClass, mas não vice-versa.
Exemplo - adicionando funcionalidade adicional
Diferenças de implementação Proxy, Decorador, Adaptador
O adaptador fornece uma interface diferente para o assunto. O proxy fornece a mesma interface. O Decorator fornece uma interface aprimorada.
A maioria das informações nesta resposta é de https://sourcemaking.com/design_patterns , que eu recomendo como um excelente recurso para padrões de design.
fonte
Eu acredito que o código dará uma ideia clara (para complementar as respostas de outras pessoas também). Veja abaixo (concentre os tipos que uma classe implementa e envolve)
fonte
O padrão de design não é matemática, é uma combinação de arte e engenharia de software. Para esse requisito, não há nada que você precise usar proxy, ponte etc. Os padrões de design são criados para resolver os problemas. Se você antecipar um problema de design, use-o. Com base na experiência, você conhecerá um problema específico, qual padrão usar. Se você é bom em sólidos princípios de design, teria implementado o padrão de design sem saber que é padrão. Exemplo comum é padrões estéticos e de fábrica
Portanto, concentre-se mais em princípios sólidos de design, princípios de codificação limpos e ttd
fonte