Pergunta

Eu estava olhando para o padrão Proxy, e me parece muito com os padrões Decorator, adaptador e Bridge. Estou mal-entendido alguma coisa? Qual é a diferença? Por que eu iria usar o padrão Proxy contra os outros? Como você tem usado eles no passado em projetos do mundo real?

Foi útil?

Solução

Proxy, decorador, adaptador e Ponte são todas as variações sobre "wrapping" uma classe. Mas seus usos são diferentes.

  • Proxy pode ser usado quando você quer lazy-instanciar um objeto, ou ocultar o fato de que você está chamando um serviço remoto, ou controlar o acesso ao objeto.

  • Decorator é também chamado de "Proxy Inteligente." Isto é usado quando você deseja adicionar funcionalidade a um objeto, mas não pela extensão tipo desse objeto. Isso permite que você a fazê-lo em tempo de execução.

  • O adaptador é usado quando você tem uma interface abstrata, e você deseja mapear essa interface para outro objeto que tem papel funcional semelhante, mas uma interface diferente.

  • Ponte é muito semelhante ao adaptador, mas chamá-lo ponte quando você definir tanto a interface abstrata e a implementação subjacente. Ou seja, você não está adaptando a algum legado ou código de terceiros, você é o designer de todo o código, mas você precisa ser capaz de trocar diferentes implementações.

  • Fachada é um de nível superior (leia-se: mais simples) interface para um subsistema de uma ou mais classes. Suponha que você tenha um conceito complexo que requer vários objetos para representar. Fazer alterações a esse conjunto de objetos é confuso, porque você não sabe sempre qual objeto tem o método você precisa chamar. Esse é o tempo para escrever uma fachada que fornece métodos de alto nível para todas as operações complexas que você pode fazer para a 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

Outras dicas

Como a resposta de Bill diz, os casos de uso são diferentes .

Assim são as suas estruturas.

  • proxy e decorador ambos têm a mesma interface como os seus tipos embrulhados, mas o proxy cria uma instância sob o capô, ao passo que o decorador leva uma instância em o construtor.

  • O adaptador e Fachada ambos têm uma interface diferente do que eles embrulhar. Mas os deriva adaptador de uma interface existente, enquanto que a fachada cria uma nova interface.

  • Ponte e O adaptador ambos ponto em um tipo existente. Mas a ponte vai apontar para um tipo abstrato, e o adaptador pode apontar para um tipo concreto. A ponte vai permitir que você emparelhar a implementação em tempo de execução, enquanto o adaptador normalmente não vai.

A minha opinião sobre o assunto.

Todos os quatro padrões têm muito em comum, todos os quatro são às vezes chamados informalmente wrappers, ou padrões de mensagens publicitárias. Tudo composição uso, sujeito acondicionamento e delegar a execução para o assunto em algum momento, fazer mapeamento um método de chamada para outra. Eles cliente de reposição a necessidade de ter que construir um objeto diferente e copiar todos os dados relevantes. Se usado com sabedoria, eles economizar memória e processador.

Ao promover solto acoplamento eles fazem uma vez código estável menos expostos a mudanças inevitáveis ??e melhor legível para outros desenvolvedores.

O adaptador

Adaptador adapta assunto (Adaptee) para uma interface diferente. Desta forma, podemos adicionar objeto ser colocado a uma coleção de nominalmente diferentes tipos.

Adaptador expor apenas os métodos relevantes para o cliente, pode restringir todas as outras, as intenções de uso reveladoras para contextos específicos, como adaptar biblioteca externa, fazer parecer menos geral e mais focados em nossos necessidades de aplicação. Adaptadores de aumentar a legibilidade e auto descrição do nosso código.

Adaptadores escudos equipe de um de código volátil de outras equipes; uma ferramenta de Salvador de vida quando se trata de equipes offshore; -)

Menos mencionado efeito, para evitar que a classe assunto a partir de excesso de anotações. Com tantas estruturas com base em anotações isso se torna o uso mais importante do que nunca.

Adaptador ajuda a contornar a limitação Java de apenas herança simples. Pode combinar vários adaptees sob um envelope dando impressão de herança múltipla.

Código sábio, adaptador é “fina”. Ele não deve acrescentar muito código para a classe Adaptee, além de simplesmente chamar o método Adaptee e conversões de dados ocasionais necessário fazer essas chamadas.

Não há muitos exemplos de adaptadores boa em JDK ou bibliotecas básicas. Os desenvolvedores de aplicativos criar adaptadores, para se adaptar bibliotecas para interfaces específicas de aplicação.

Decorator

Decorator não só delegar, não só mapeia um método para outro, eles fazem mais, eles modificar o comportamento de alguns métodos de assunto, ele pode decidir método assunto não chamada em tudo, delegado para um objeto diferente, um objeto auxiliar.

decoradores tipicamente adicionar funcionalidade (transparente) para objeto embrulhado como log, encriptação, formatação, ou compressão para sujeito. Esta funcionalidade Nova pode trazer um monte de novo código. Assim, decoradores são geralmente muito mais “gordo”, em seguida, Adaptadores.

Decorator deve ser uma sub-classe de interface do sujeito. Eles podem ser usados ??de forma transparente, em vez de seus súditos. Veja BufferedOutputStream, ainda é OutputStream e pode ser usado como tal. Isso é uma grande diferença técnica de adaptadores.

exemplos do livro de texto de decoradores toda a família está prontamente no JDK - Java IO. Todas as classes, como BufferedOutputStream , FilterOutputStream e ObjectOutputStream são decoradores de OutputStream . Eles podem ser cebola em camadas, onde se um decorador é decorada de novo, adicionando mais funcionalidade.

Proxy

Proxy não é uma embalagem típica. O objeto embrulhado, o assunto proxy, pode ainda não existir no momento da criação do proxy. Proxy muitas vezes cria-lo internamente. Pode ser um objeto pesado criado sob demanda, ou é objeto remoto em diferentes JVM ou nó de rede diferente e até mesmo um objeto não-Java, um componente em código nativo. Ele não tem que envoltório ou delegado necessário para outro objeto em tudo.

A maioria dos exemplos típicos são proxies remotos, objeto pesado initializers e proxies de acesso.

  • Proxy Remoto - assunto é no servidor remoto, diferente JVM ou mesmo não sistema Java. Proxy traduz chamadas de método para RMI / REST / chamadas SOAP ou o que for necessário, protegendo o cliente contra a exposição ao subjacente tecnologia.

  • Carga Tardia Proxy - objeto totalmente initialize apenas o primeiro uso ou primeiro uso intensivo.

  • Acesso Proxy -. Controlar o acesso ao assunto

Fachada

Fachada está intimamente associada com o princípio de design do Menor Conhecimento (Lei de Demeter). Fachada é muito semelhante ao adaptador. Ambos envoltório, ambos mapa um objeto para outro, mas eles diferem na intenção. Fachada achata a estrutura complexa de um sujeito, objecto gráfico complexo, simplificando o acesso a uma estrutura complexa.

Fachada envolve uma estrutura complexa, fornecendo uma interface simples para ele. Este objecto cliente impede de ser exposto às relações internas na estrutura do sujeito, portanto, que promovem o acoplamento fraco.

Ponte

Mais variante complexa do padrão Adapter onde não só a implementação varia, mas também abstração. Ele adiciona mais um engano para a delegação. A delegação extra é a ponte. Ele separa Adapter mesmo de adaptar interface. Ele aumenta a complexidade mais do que qualquer outro dos outros padrões de acondicionamento, para que aplique com cuidado.

As diferenças de construtores

diferenças padrão também são óbvias quando se olha para os seus construtores.

  • Proxy é não envolver um objeto existente. Não há assunto no construtor.

  • Decorator e O adaptador faz envoltório objeto já existente, e tal é tipicamente
    fornecida no construtor.

  • Fachada construtor recebe elemento raiz de um gráfico do objeto inteiro, caso contrário, parece mesmo que adaptador.

A vida real exemplo - JAXB Marshalling Adapter . Objectivo do presente adaptador é mapeamento de uma classe plana simples de estrutura mais complexa exigida externamente e para impedir "poluentes" classe sujeito com anotações excessivas.

Há uma grande quantidade de sobreposição em muitos dos padrões GoF. Eles estão todos construídos sobre o poder do polimorfismo e, por vezes, realmente só diferem na intenção. (Estado estratégia vs.)

O meu entendimento dos padrões de aumento de 100 vezes depois de ler Head First Design Patterns .

Eu recomendo!

Todas as boas respostas de especialistas já explicou o que faz cada padrão representa.

eu vou Decore pontos-chave.

Decorator:

  1. Adicionar comportamento de objeto em tempo de execução . A herança é a chave para obter essa funcionalidade, que é ao mesmo tempo vantagens e desvantagens deste padrão.
  2. Ele modifica o comportamento de interface.

por exemplo. (Com encadeamento): classes de pacotes java.io relacionadas com InputStream & OutputStream as interfaces

FileOutputStream fos1 = new FileOutputStream("data1.txt");  
ObjectOutputStream out1 = new ObjectOutputStream(fos1);

Proxy:

  1. usá-lo para inicialização lenta, melhoria de desempenho, armazenando o objeto e controlar o acesso ao cliente / chamador . Ele pode fornecer comportamento alternativo ou ligue objeto real. Durante este processo, pode criar um novo objeto.
  2. Ao contrário de Decorator , que permite o encadeamento de objetos, Proxy não permite o encadeamento.

g .: classes de pacotes java.rmi.

Adaptador:

  1. Ele permite que duas interfaces independentes para trabalhar em conjunto através dos objetos diferentes , possivelmente jogando mesmo papel.
  2. Ele modifica interface original .

por exemplo. java.io.InputStreamReader (InputStream retorna um Reader)

Bridge:

  1. Ele permite que ambas as abstrações e implementações para variar independentemente .
  2. Ele usa composição sobre herança .

por exemplo. classes de coleção em java.util. List implementado por ArrayList.

Notas-chave:

  1. O adaptador fornece uma interface diferente para seu assunto. Proxy fornece a mesma interface. Decorator fornece uma interface melhorada.
  2. O adaptador mudanças na interface de um objeto, Decorator aumenta as responsabilidades de um objeto.
  3. Decorator e Proxy têm diferentes finalidades, mas estruturas semelhantes
  4. O adaptador faz as coisas funcionarem após eles são projetados; Ponte torna o trabalho antes que eles são.
  5. Ponte é projetado up-front para deixar a abstração ea implementação variar independentemente. O adaptador é adaptado para fazer aulas não relacionados trabalhar juntos
  6. Decorator é projetado para permitir que você adicionar responsabilidades a objetos sem subclassificação.

Tenha um olhar em grandes SE perguntas / artigos sobre exemplos de vários padrões de projeto

Quando usar o padrão Decorator?

Quando você usa o padrão Bridge? Como é que é diferente do padrão Adapter?

Diferenças entre Proxy e Decorator Pattern

Eles são bastante semelhantes, e as linhas entre eles são bastante cinza. Eu sugiro que você leia o Padrão Proxy e entradas Decorator padrão no wiki c2.

As entradas e discussões há bastante extensa, e eles também conectar-se a outros artigos relevantes. By the way, o wiki c2 é excelente quando perguntando sobre as nuances entre diferentes padrões.

Para resumir as entradas c2-se, eu diria que um decorador adiciona / muda o comportamento, mas um proxy tem mais a ver com controle de acesso (instanciação preguiçoso, acesso remoto, segurança etc). Mas como eu disse, as linhas entre eles são cinza, e eu vejo referências a proxies que poderiam ser facilmente vistos como decoradores e vice-versa.

Esta é citação de Head First Design Patterns

Definições pertence ao livro. Exemplos pertence a mim.

Decorator - não altera a interface, mas acrescenta responsabilidade. Suponha que você tenha uma interface de carro, quando você implementar isso para diferente modelo do carro (s, sv, sl) pode ser necessário adicionar mais responsabilidade para alguns modelos. Como tem teto solar, airbag etc ..

O adaptador - converte uma interface para outra. Você tem uma interface de carro e você gostaria que agem como jipe. Então você levar o carro, modificá-lo e se transformar em um jipe. Uma vez que não é um verdadeiro jipe. Mas age como um jipe.

Fachada - Faz uma interface mais simples. Suponha que você tenha interfaces de carro, de avião, de navio. Na verdade tudo o que você precisa é de uma classe que envia as pessoas de um local para outro. Você quer fachada para decidir o veículo para uso. Então você coletar todas essas referências de interface com menos de 1 guarda-chuva e deixá-lo decidir / delegado para mantê-lo simples.

Head First: "A fachada não só simplifica uma interface, que separa um cliente de um subsistema de componentes. Fachadas e adaptadores podem envolver várias classes, mas a intenção do fachada é simplificar, enquanto de um adaptador é converter a interface para algo diferente. "

Todos os quatro padrões envolvem embrulho interior objeto / classe com um exterior, então eles são muito semelhantes estruturalmente. Eu delinear diferença pelo propósito:

  • Proxy encapsula o acesso no exterior para interior.
  • decorador fortes modifica ou estende-se o comportamento de interior com exterior.
  • Adaptador convertidos a interface do interior para o exterior.
  • ponte separa parte invariável de comportamento (exterior) a partir de variáveis ??ou parte dependente da plataforma (interior).

E por variação interface entre objectos internos e externos:

  • em Proxy interfaces são o mesmo.
  • em Decorator interfaces são o mesmo.
  • em O adaptador interfaces são diferentes formalmente, mas cumprir a mesma finalidade.
  • em Ponte interfaces são diferentes conceitualmente.

Eu uso-o muitas vezes ao consumir serviços web. O padrão Proxy provavelmente deve ser renomeado para algo mais pragmática, como Padrão 'Wrapper". Eu também tenho uma biblioteca que é um proxy para MS Excel. Torna-se muito fácil para automatizar Excel, sem ter que se preocupar com fundo detalhes, como o que versão está instalado (se houver).

Falando implementação detalhes, eu encontrar uma diferença entre Proxy e decorador, adaptador, Fachada ... Em comum implementação desses padrões há um objeto de destino envolto por um objeto de inclusão. usos cliente que encerram objeto em vez de objeto de destino. E o objeto de destino realmente desempenhar um papel importante dentro de alguns dos métodos de anexando objeto.

No entanto, em caso de Proxy, anexando objeto pode jogar alguns métodos por si só, ele só inicializar objeto de destino quando o cliente chama alguns métodos que necessita objeto alvo participar. Esta é a inicialização lenta. No caso de outros padrões, objeto envolvente é praticamente baseado sobre o objecto alvo. Então objeto de destino é sempre inicializado juntamente com colocando objeto em construtores / setters.

Outra coisa, um proxy faz exatamente o que um alvo faz enquanto outros padrões de adicionar mais funcionalidades ao alvo.

Eu gostaria de adicionar exemplos para resposta Bill Karwing (o que é ótimo btw). Eu também adicionar algumas diferenças fundamentais de implementação, que eu sinto estão faltando

Peças cotados são de resposta de [ https://stackoverflow.com/a/350471/1984346] ( Bill Karwing)

Proxy, decorador, adaptador e Ponte são todas as variações sobre "wrapping" uma classe. Mas seus usos são diferentes.

  • Proxy pode ser usado quando você quer lazy-instanciar um objeto, ou esconder o fato de que você está chamando um serviço remoto ou controle de acesso para o objeto.

ProxyClass e ObjectClass que é proxy, deve implementar mesma interface, de modo que eles são intercambiáveis ??

Exemplo - proxy objecto caro

class ProxyHumanGenome implements GenomeInterface  {
    private $humanGenome = NULL; 

    // humanGenome class is not instantiated at construct time
    function __construct() {
    }

    function getGenomeCount() {
        if (NULL == $this->humanGenome) {
            $this->instantiateGenomeClass(); 
        }
        return $this->humanGenome->getGenomeCount();
    }
} 
class HumanGenome implement GenomeInterface { ... }
  • Decorator é também chamado de "Proxy Inteligente." Isto é usado quando você quer adicionar funcionalidade a um objeto, mas não através da extensão desse objeto tipo. Isso permite que você a fazê-lo em tempo de execução.

DecoratorClass deveria (poderia) implementar a interface estendida do ObjectClass. Assim, o ObjectClass poderia ser substituído por DecoratorClass, mas não vice-versa.

Exemplo - adicionar funcionalidade adição

class DecoratorHumanGenome implements CheckGenomeInterface  {

    // ... same code as previous example

    // added functionality
    public function isComplete() {
        $this->humanGenome->getCount >= 21000
    }
}

interface CheckGenomeInterface extends GenomeInterface {

    public function isComplete();

}

class HumanGenome implement GenomeInterface { ... }
  • O adaptador é usado quando você tem uma interface abstrata, e você quer mapear a interface para um outro objecto semelhante que tem funcional papel, mas uma interface diferente.

diferenças Implentation Proxy, decorador, adaptador

adaptador fornece uma interface diferente para seu assunto. Proxy proporciona a mesma interface. Decorator fornece uma interface melhorada.

  • Ponte é muito semelhante ao adaptador, mas chamá-lo ponte quando você definir tanto a interface abstrata e a implementação subjacente. Ou seja, você não está adaptando a algum legado ou código de terceiros, você está O designer de todo o código, mas você precisa ser capaz de trocar diferentes implementações.

  • Fachada é um de nível superior (leia-se: mais simples) interface para um subsistema de uma ou mais classes. Suponha que você tenha um conceito complexo que requer vários objetos para representar. Fazer alterações a esse conjunto de objetos é confuso, porque você não sabe sempre qual objeto tem o método você precisa chamar. Esse é o tempo para escrever uma fachada que fornece métodos de alto nível para todas as operações complexas que você pode fazer para a coleção de objetos. Exemplo: um Modelo de Domínio para uma escola seção, com métodos como countStudents(), reportAttendance(), assignSubstituteTeacher(), e assim por diante.

A maioria da informação nesta resposta é de https://sourcemaking.com/design_patterns , que eu recomendo como um excelente recurso para padrões de projeto.

Eu acredito que o código lhe dará algumas idéias claras (para complementar outras respostas também). Por favor, veja abaixo, (foco os tipos que uma classe implementa e wraps)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Proxy */

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("PROXY");
            Console.WriteLine(Environment.NewLine);

            //instead of creating here create using a factory method, the facory method will return the proxy
            IReal realProxy = new RealProxy();
            Console.WriteLine("calling do work with the proxy object ");
            realProxy.DoWork();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("ADAPTER");
            Console.WriteLine(Environment.NewLine);

            /*Adapter*/
            IInHand objectIHave = new InHand();
            Api myApi = new Api();
            //myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
            IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
            Console.WriteLine("calling api with  my adapted obj");
            myApi.SomeApi(myAdaptedObject);


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("DECORATOR");
            Console.WriteLine(Environment.NewLine);

            /*Decorator*/
            IReady maleReady = new Male();
            Console.WriteLine("now male is going to get ready himself");
            maleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReady = new Female();
            Console.WriteLine("now female is going to get ready her self");
            femaleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady maleReadyByBeautician = new Beautician(maleReady);
            Console.WriteLine("now male is going to get ready by beautician");
            maleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReadyByBeautician = new Beautician(femaleReady);
            Console.WriteLine("now female is going to get ready by beautician");
            femaleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            Console.ReadLine();


        }
    }

    /*Proxy*/

    public interface IReal
    {
        void DoWork();
    }

    public class Real : IReal
    {
        public void DoWork()
        {
            Console.WriteLine("real is doing work ");
        }
    }


    public class RealProxy : IReal
    {
        IReal real = new Real();

        public void DoWork()
        {
            real.DoWork();
        }
    }

    /*Adapter*/

    public interface IActual
    {
        void DoWork();
    }

    public class Api
    {
        public void SomeApi(IActual actual)
        {
            actual.DoWork();
        }
    }

    public interface IInHand
    {
        void DoWorkDifferently();
    }

    public class InHand : IInHand
    {
        public void DoWorkDifferently()
        {
            Console.WriteLine("doing work slightly different ");
        }
    }

    public class ActualAdapterForInHand : IActual
    {
        IInHand hand = null;

        public ActualAdapterForInHand()
        {
            hand = new InHand();
        }

        public ActualAdapterForInHand(IInHand hnd)
        {
            hand = hnd;
        }

        public void DoWork()
        {
            hand.DoWorkDifferently();
        }
    }

    /*Decorator*/

    public interface IReady
    {
        void GetReady();
    }

    public class Male : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
        }
    }

    public class Female : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
            Console.WriteLine("Make up....");
        }
    }

    //this is a decorator
    public class Beautician : IReady
    {
        IReady ready = null;

        public Beautician(IReady rdy)
        {
            ready = rdy;
        }

        public void GetReady()
        {
            ready.GetReady();
            Console.WriteLine("Style hair ");

            if (ready is Female)
            {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("doing ready process " + i);
                }

            }
        }
    }

}

projeto padrão não é matemática, é combinação de arte e engenharia de software. Não há nada como para este requirment você tem que usar proxy, ponte etc. Projeto padrões são criados para resolver os problemas. Se você antecipar um problema de design, em seguida, usá-lo. Com base na experiência, você vai saber com problema específico, qual padrão de usar. Se você é bom em princípios de design sólido, você teria aplicado padrão de projeto sem conhecê-lo é o padrão. exemplo comum é padrões statergy e fábrica

Daí concentrar mais em princípios Desighn sólidos, princípios de codificação limpas e TTD

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top