Quais são alguns dos comuns , exemplos do mundo real de usar o padrão Builder? O que isso te compra? Por que não usar apenas um padrão de fábrica?
java
design-patterns
builder
Charles Graham
fonte
fonte
Respostas:
A principal diferença entre um construtor e um IMHO de fábrica é que um construtor é útil quando você precisa fazer muitas coisas para construir um objeto. Por exemplo, imagine um DOM. Você precisa criar muitos nós e atributos para obter seu objeto final. Uma fábrica é usada quando a fábrica pode criar facilmente o objeto inteiro em uma chamada de método.
Um exemplo de uso de um construtor é a construção de um documento XML; usei esse modelo ao criar fragmentos HTML; por exemplo, posso ter um construtor para criar um tipo específico de tabela e pode ter os seguintes métodos (os parâmetros não são mostrados) :
Esse construtor cuspiria o HTML para mim. Isso é muito mais fácil de ler do que percorrer um grande método processual.
Confira o Builder Pattern na Wikipedia .
fonte
Abaixo estão alguns motivos para argumentar sobre o uso do padrão e código de exemplo em Java, mas é uma implementação do Padrão do Construtor coberto pela Gang of Four nos Design Patterns . Os motivos pelos quais você o usaria em Java também são aplicáveis a outras linguagens de programação.
Como Joshua Bloch afirma em Java Efetivo, 2ª Edição :
Em algum momento, todos encontramos uma classe com uma lista de construtores em que cada adição adiciona um novo parâmetro de opção:
Isso é chamado de Padrão do Construtor Telescópico. O problema com esse padrão é que, uma vez que os construtores têm 4 ou 5 parâmetros, fica difícil lembrar a ordem necessária dos parâmetros , bem como qual construtor específico você deseja em uma determinada situação.
Uma alternativa que você tem para o Telescoping Constructor Pattern é o JavaBean Pattern, no qual você chama um construtor com os parâmetros obrigatórios e, em seguida, chama os setters opcionais após:
O problema aqui é que, como o objeto é criado por várias chamadas, ele pode estar em um estado inconsistente no meio de sua construção. Isso também requer muito esforço extra para garantir a segurança do encadeamento.
A melhor alternativa é usar o Padrão do Construtor.
Observe que Pizza é imutável e que os valores dos parâmetros estão todos em um único local . Como os métodos setter do Builder retornam o objeto Builder, eles podem ser encadeados .
Isso resulta em um código fácil de escrever e muito fácil de ler e entender.Neste exemplo, o método de construção pode ser modificado para verificar os parâmetros após serem copiados do construtor para o objeto Pizza e lançar uma IllegalStateException se um valor de parâmetro inválido tiver sido fornecido. Esse padrão é flexível e é fácil adicionar mais parâmetros no futuro. É realmente útil apenas se você tiver mais de 4 ou 5 parâmetros para um construtor. Dito isto, pode valer a pena em primeiro lugar, se você suspeitar que esteja adicionando mais parâmetros no futuro.
Eu emprestei muito esse tópico do livro Effective Java, 2nd Edition, de Joshua Bloch. Para saber mais sobre esse padrão e outras práticas Java eficazes, eu o recomendo.
fonte
new Pizza.Builder(12).cheese().pepperoni().bacon().build();
Pizza.Builder(12).cheese().pepperoni().bacon().build();
você precisaria recompilar seu código ou ter uma lógica desnecessária se precisar apenas de pepperoni pizzas. No mínimo, você também deve fornecer versões parametrizadas, como o @Kamikaze Mercenary originalmente sugerido.Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build();
. Por outro lado, nunca testamos a unidade, não é?Considere um restaurante. A criação da "refeição de hoje" é um padrão de fábrica, porque você diz à cozinha "leve-me a refeição de hoje" e a cozinha (fábrica) decide qual objeto gerar, com base em critérios ocultos.
O construtor será exibido se você solicitar uma pizza personalizada. Nesse caso, o garçom diz ao chef (construtor): "Eu preciso de uma pizza; adicione queijo, cebola e bacon a ela!" Portanto, o construtor expõe os atributos que o objeto gerado deve ter, mas oculta como configurá-los.
fonte
A classe .NET StringBuilder é um ótimo exemplo de padrão de construtor. É usado principalmente para criar uma string em uma série de etapas. O resultado final que você faz ToString () é sempre uma string, mas a criação dessa string varia de acordo com as funções da classe StringBuilder que foram usadas. Em resumo, a idéia básica é construir objetos complexos e ocultar os detalhes de implementação de como está sendo construído.
fonte
b.append(...).append(...)
antes de finalmente chamartoString()
. Citação: infoq.com/articles/internal-dsls-javaPara um problema multithread, precisamos de um objeto complexo para ser construído para cada thread. O objeto representou os dados que estão sendo processados e pode mudar dependendo da entrada do usuário.
Poderíamos usar uma fábrica? sim
Por que nós não? Construtor faz mais sentido, eu acho.
As fábricas são usadas para criar diferentes tipos de objetos que são do mesmo tipo básico (implementam a mesma interface ou classe base).
Os construtores constroem o mesmo tipo de objeto repetidamente, mas a construção é dinâmica, portanto pode ser alterada em tempo de execução.
fonte
Você o usa quando tem muitas opções para lidar. Pense em coisas como jmock:
Parece muito mais natural e é ... possível.
Há também a construção de XML, a construção de strings e muitas outras coisas. Imagine se
java.util.Map
tivesse colocado como construtor. Você poderia fazer coisas assim:fonte
Ao passar pela estrutura do Microsoft MVC, pensei em um padrão de construtor. Me deparei com o padrão na classe ControllerBuilder. Esta classe é para retornar a classe de fábrica do controlador, que é usada para construir o controlador de concreto.
A vantagem que vejo ao usar o padrão do construtor é que você pode criar sua própria fábrica e conectá-la à estrutura.
@Tetha, pode haver um restaurante (Framework) administrado por um italiano, que serve Pizza. Para preparar uma pizza, o italiano (Object Builder) usa Owen (Factory) com uma base de pizza (classe base).
Agora, o indiano assume o restaurante do italiano. Servidores de restaurante indiano (Framework) dosa em vez de pizza. Para preparar a dosa, o índio (construtor de objetos) usa a Frigideira (Fábrica) com um Maida (classe base)
Se você observar o cenário, a comida é diferente, a maneira como a comida é preparada é diferente, mas no mesmo restaurante (sob a mesma estrutura). O restaurante deve ser construído de forma a poder apoiar cozinha chinesa, mexicana ou qualquer outra cozinha. O construtor de objetos dentro da estrutura facilita o plug-in do tipo de cozinha que você deseja. por exemplo
fonte
Eu sempre não gostei do padrão Builder como algo pesado, intrusivo e muitas vezes abusado por programadores menos experientes. É um padrão que só faz sentido se você precisar montar o objeto a partir de alguns dados que exijam uma etapa de pós-inicialização (ou seja, depois que todos os dados forem coletados - faça algo com ele). Em vez disso, em 99% do tempo, os construtores são simplesmente usados para inicializar os alunos.
Nesses casos, é muito melhor simplesmente declarar
withXyz(...)
criadores de tipos dentro da classe e fazê-los retornar uma referência a si mesma.Considere isto:
Agora temos uma classe única organizada que gerencia sua própria inicialização e faz praticamente o mesmo trabalho que o construtor, exceto que é muito mais elegante.
fonte
Outra vantagem do construtor é que, se você tiver um Factory, ainda há algum acoplamento no seu código, porque para o Factory funcionar, ele precisa conhecer todos os objetos que ele pode criar. . Se você adicionar outro objeto que possa ser criado, precisará modificar a classe de fábrica para incluí-lo. Isso também acontece na Abstract Factory.
Com o construtor, por outro lado, você apenas precisa criar um novo construtor de concreto para essa nova classe. A classe diretor permanecerá a mesma, porque recebe o construtor no construtor.
Além disso, existem muitos sabores do construtor. O Kamikaze Mercenary`s dá outro.
fonte
fonte
Com base nas respostas anteriores (trocadilho intencional), um excelente exemplo do mundo real é o suporte incorporado ao Groovy
Builders
.MarkupBuilder
StreamingMarkupBuilder
SwingXBuilder
Consulte Construtores na documentação do Groovy
fonte
Eu usei o construtor na biblioteca de mensagens criada em casa. O núcleo da biblioteca estava recebendo dados da ligação, coletando-os com a instância do Builder e, assim que o Builder decidiu que tinha tudo o que era necessário para criar uma instância de Message, o Builder.GetMessage () estava construindo uma instância de mensagem usando os dados coletados do fio.
fonte
Confira o InnerBuilder, um plug-in do IntelliJ IDEA que adiciona uma ação 'Builder' ao menu Generate (Alt + Insert), que gera uma classe interna do construtor, conforme descrito em Java Efetivo
https://github.com/analytically/innerbuilder
fonte
Quando eu queria usar o XMLGregorianCalendar padrão para o meu XML objetar a organização do DateTime em Java, ouvi muitos comentários sobre o peso e a complexidade do uso dele. Eu estava tentando controlar os campos XML nas estruturas xs: datetime para gerenciar fuso horário, milissegundos etc.
Por isso, projetei um utilitário para criar um calendário XMLGregorian a partir de um GregorianCalendar ou java.util.Date.
Por causa de onde trabalho, não tenho permissão para compartilhá-lo online sem legal, mas aqui está um exemplo de como um cliente o usa. Ele abstrai os detalhes e filtra parte da implementação do XMLGregorianCalendar que é menos usada para xs: datetime.
Concedido que esse padrão é mais um filtro, pois define os campos no xmlCalendar como indefinidos para que sejam excluídos, ele ainda o "constrói". Adicionei facilmente outras opções ao construtor para criar uma estrutura xs: date e xs: time e também para manipular compensações de fuso horário quando necessário.
Se você já viu um código que cria e usa XMLGregorianCalendar, verá como isso facilitou muito a manipulação.
fonte
Um ótimo exemplo do mundo real é usar ao testar suas classes. Você usa construtores sut (System Under Test).
Exemplo:
Classe:
Teste:
sut Builder:
fonte
CustomAuthenticationService
classe?