Qual é a diferença entre o padrão Builder Design e o padrão Factory Design?

663

Qual é a diferença entre o padrão de design do Builder e o padrão de design da fábrica?

Qual é o mais vantajoso e por quê?

Como represento minhas descobertas como um gráfico se quero testar e comparar / contrastar esses padrões?

Penguen
fonte
13
Uma vez que eles fazem coisas diferentes, o que você quer dizer com "vantajoso"?
S.Lott
5
O Builder é uma versão mais complexa do construtor - enquanto o método de fábrica é simplificado.
Dávid Horváth
@ DávidHorváth Eu não descreveria um Construtor como "mais complexo". Quando você lida com um construtor que possui 100 parâmetros e se preocupa apenas com 3 deles, e sabe que o número de parâmetros pode mudar no futuro, o uso do padrão Builder tornaria a vida de todos muito mais simples.
Aberrant
@Aberrant O uso complicado e a complexidade arquitetural são duas coisas diferentes. Eu me concentrei no último.
Dávid Horváth

Respostas:

466

Com padrões de design, geralmente não há solução "mais vantajosa" que funcione para todos os casos. Depende do que você precisa implementar.

Da Wikipedia:

  • O Builder se concentra na construção passo a passo de um objeto complexo. Resumo O Factory enfatiza uma família de objetos do produto (simples ou complexos). O Builder retorna o produto como uma etapa final, mas no que diz respeito à Abstract Factory, o produto é retornado imediatamente.
  • O construtor geralmente cria um composto.
  • Freqüentemente, os projetos começam usando o Método de Fábrica (menos complicado, mais personalizável, as subclasses proliferam) e evoluem para Abstract Factory, Prototype ou Builder (mais flexível, mais complexo) à medida que o designer descobre onde é necessária mais flexibilidade.
  • Às vezes, os padrões criacionais são complementares: o Builder pode usar um dos outros padrões para implementar quais componentes são criados. Abstract Factory, Builder e Prototype podem usar Singleton em suas implementações.

Entrada da Wikipedia para padrão de design de fábrica: http://en.wikipedia.org/wiki/Factory_method_pattern

Entrada da Wikipedia para o padrão de design do construtor: http://en.wikipedia.org/wiki/Builder_pattern

Adrian Grigore
fonte
159
Essa é exatamente a diferença. O Construtor é necessário apenas quando um objeto não pode ser produzido em uma etapa. Um excelente exemplo disso seria o processo de desserialização de um objeto complexo. Muitas vezes, os parâmetros para o objeto complexo devem ser recuperados um por um.
Bernard Igiri 24/03
1
Para a primeira frase, eu diria que geralmente há uma solução mais vantajosa que se aplica amplamente ... simplesmente não as vemos, porque elas acabam sendo inseridas diretamente nas linguagens de programação.
Joel Coehoorn
4
@ Joel: Eu concordo que alguns padrões são mais comuns que outros (por exemplo, o Factory parece ser mais comum que o Builder), mas o que eu quis dizer é que nenhum deles é sempre melhor que o outro, independentemente da aparência do cenário. .
Adrian Grigore
@AdrianGrigore e se misturar os dois ?? aso.net mvc tem ControllerBuilder que definiu e obtém o método para a classe ControllerFactory
AminM
Boa resposta, embora duas coisas que valham a pena adicionar sejam: 1) O Builder é usado principalmente para criar POJOs usando a API Fluent (por exemplo, Person.builder (). WithName ("Sam"). WithAge (38) .build (). 2) Na minha experiência, o construtor é útil para a criação de POJO para objetos de domínio, enquanto o factory é útil para criar objetos de serviço como a classe PdfGeneratorFactory. O objeto de serviço pode ser armazenado em cache na fábrica para uso por mais de um tempo, enquanto o construtor sempre cria um novo objeto por design.
saurabh.in
359

Uma fábrica é simplesmente uma função de wrapper em torno de um construtor (possivelmente um em uma classe diferente). A principal diferença é que um padrão de método de fábrica exige que todo o objeto seja construído em uma única chamada de método, com todos os parâmetros passados ​​em uma única linha. O objeto final será retornado.

Um padrão de construtor , por outro lado, é essencialmente um objeto de wrapper em torno de todos os parâmetros possíveis que você pode querer passar para uma chamada de construtor. Isso permite que você use métodos de configuração para criar lentamente sua lista de parâmetros. Um método adicional em uma classe de construtor é um método build (), que simplesmente passa o objeto construtor para o construtor desejado e retorna o resultado.

Em linguagens estáticas como Java, isso se torna mais importante quando você tem mais do que um punhado de parâmetros (potencialmente opcionais), pois evita a necessidade de ter construtores telescópicos para todas as combinações possíveis de parâmetros. Além disso, um construtor permite que você use métodos setter para definir campos somente leitura ou privados que não podem ser modificados diretamente após a chamada do construtor.

Exemplo básico de fábrica

// Factory
static class FruitFactory {
    static Fruit create(name, color, firmness) {
        // Additional logic
        return new Fruit(name, color, firmness);
    }
}

// Usage
Fruit fruit = FruitFactory.create("apple", "red", "crunchy");

Exemplo básico do construtor

// Builder
class FruitBuilder {
    String name, color, firmness;
    FruitBuilder setName(name)         { this.name     = name;     return this; }
    FruitBuilder setColor(color)       { this.color    = color;    return this; }
    FruitBuilder setFirmness(firmness) { this.firmness = firmness; return this; }
    Fruit build() {
        return new Fruit(this); // Pass in the builder
    }
}

// Usage
Fruit fruit = new FruitBuilder()
        .setName("apple")
        .setColor("red")
        .setFirmness("crunchy")
        .build();

Vale a pena comparar os exemplos de código dessas duas páginas da Wikipedia:

http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Builder_pattern

James McGuigan
fonte
1
Esse não é o uso correto do padrão do construtor imo, mesmo no link do wiki que você utilizou é diferente. Esse FruitBuilder é uma combinação de componentes do Director e do Builder nos quais você chama build () que deve pertencer ao Director e setters que pertencem ao componente do Builder. O Director deve conter lógica de negócios sobre como criar objetos usando os métodos Builders. Apis fluentes não são padrões de construtor e StringBuilder também não é padrão de construtor.
Kmaczek 5/05/19
282

O padrão Factory quase pode ser visto como uma versão simplificada do padrão Builder.

No padrão de fábrica , a fábrica é responsável por criar vários subtipos de um objeto, dependendo das necessidades.

O usuário de um método de fábrica não precisa saber o subtipo exato desse objeto. Um exemplo de método de fábrica createCarpode retornar um Fordou um Hondaobjeto digitado.

No padrão Construtor , subtipos diferentes também são criados por um método construtor, mas a composição dos objetos pode diferir na mesma subclasse.

Para continuar o exemplo do carro, você pode ter um createCarmétodo construtor que cria um Hondaobjeto do tipo com um motor de 4 cilindros ou um Hondaobjeto do tipo com 6 cilindros. O padrão do construtor permite essa granularidade mais fina.

Diagramas do padrão Builder e do método Factory estão disponíveis na Wikipedia.

Ben S
fonte
13
O padrão do construtor é como ampliar a construção do grande objeto. O grande objeto é composto de outro objeto que é composto mais adiante como recursão. Enquanto a fábrica apenas recebe você em uma ligação. Este entendimento está correto?
Fooo
63

O padrão de design do construtor descreve um objeto que sabe criar outro objeto de um tipo específico em várias etapas. Ele mantém o estado necessário para o item de destino em cada etapa intermediária. Pense no que StringBuilder passa para produzir uma string final.

O padrão de design da fábrica descreve um objeto que sabe como criar vários tipos diferentes, porém relacionados, de um objeto, em que o tipo específico é escolhido com base nos parâmetros fornecidos. Pense no sistema de serialização, onde você cria seu serializador e ele constrói o objeto desejado em uma chamada de carga.

Joel Coehoorn
fonte
7
Apenas uma dica: um bom exemplo para o padrão do construtor é a "interface fluente" e o ADO.NET está cheio de implementações "factory" e "abstract factory" (por exemplo, DbFactory).
224/09
50
  • Construindo um objeto complexo passo a passo: padrão do construtor

  • Um objeto simples é criado usando um único método: padrão de método de fábrica

  • Criando Objeto usando o método de várias fábricas: Resumo padrão de fábrica

Mahamudul Hasan Munna
fonte
21

Padrão de construtor e padrão de fábrica, ambos parecem muito parecidos com olhos nus, porque ambos criam objetos para você.

Mas você precisa olhar mais de perto

Este exemplo da vida real tornará a diferença entre os dois mais clara.

Suponha que você foi a um restaurante de fast food e pediu comida .

1) Que comida?

pizza

2) Quais coberturas?

Capsicum, tomate, frango de churrasco, sem abacaxi

Portanto, diferentes tipos de alimentos são feitos pelo padrão Factory, mas as diferentes variantes (sabores) de um determinado alimento são feitas pelo padrão Builder.

Diferentes tipos de alimentos

Pizza, Hamburguer, Macarrão

Variantes de Pizza

Apenas queijo, queijo + tomate + pimento, queijo + tomate etc.

Amostra de código

Você pode ver a implementação de código de amostra de ambos os padrões aqui
Builder Pattern
Factory Pattern

Rohit Singh
fonte
1
Obrigado por fornecer o código de exemplo! Seus exemplos diferenciam esses dois padrões muito bem.
Rommel Paras
18

Ambos são padrões criacionais, para criar objetos.

1) Padrão de Fábrica - Suponha que você tenha uma super classe e um número N de subclasses. O objeto criado depende de qual parâmetro / valor é passado.

2) Padrão do construtor - para criar objetos complexos.

Ex: Make a Loan Object. Loan could be house loan, car loan ,
    education loan ..etc. Each loan will have different interest rate, amount ,  
    duration ...etc. Finally a complex object created through step by step process.
Tony
fonte
12

Primeiro algumas coisas gerais a seguir minha argumentação:

O principal desafio ao projetar grandes sistemas de software é que eles precisam ser flexíveis e descomplicados para mudar. Por esse motivo, existem algumas métricas como acoplamento e coesão. Para alcançar sistemas que podem ser facilmente alterados ou ampliados em sua funcionalidade sem a necessidade de redesenhar todo o sistema a partir do zero, você pode seguir os princípios de design (como SOLID, etc.). Depois de um tempo, alguns desenvolvedores reconheceram que, se seguirem esses princípios, existem soluções semelhantes que funcionaram bem em problemas semelhantes. Essas soluções padrão acabaram sendo os padrões de design.

Portanto, os padrões de design são para ajudá-lo a seguir os princípios gerais de design, a fim de obter sistemas fracamente acoplados com alta coesão.

Respondendo à pergunta:

Ao perguntar a diferença entre dois padrões, você deve se perguntar qual padrão torna seu sistema mais flexível. Cada padrão tem seu próprio propósito de organizar dependências entre classes em seu sistema.

O Padrão de Fábrica Abstrata: GoF: "Forneça uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas".

O que isso significa: Ao fornecer uma interface como essa, a chamada para o construtor de cada produto da família é encapsulada na classe factory. E como esse é o único local em todo o sistema em que esses construtores são chamados, você pode alterar seu sistema implementando uma nova classe de fábrica. Se você trocar a representação da fábrica por outra, poderá trocar um conjunto inteiro de produtos sem tocar na maioria do seu código.

O Padrão do Construtor: GoF: “Separe a construção de um objeto complexo de sua representação para que o mesmo processo de construção possa criar representações diferentes.”

O que isso significa: Você encapsula o processo de construção em outra classe, chamada diretor (GoF). Este diretor contém o algoritmo de criação de novas instâncias do produto (por exemplo, componha um produto complexo de outras partes). Para criar as partes integrais de todo o produto, o diretor usa um construtor. Ao trocar o construtor no diretor, você pode usar o mesmo algoritmo para criar o produto, mas alterar as representações de peças únicas (e, portanto, a representação do produto). Para estender ou modificar seu sistema na representação do produto, tudo que você precisa fazer é implementar uma nova classe de construtor.

Em resumo: o objetivo do Abstract Factory Pattern é trocar um conjunto de produtos feitos para serem usados ​​juntos. O objetivo do Padrão do Construtor é encapsular o algoritmo abstrato de criação de um produto para reutilizá-lo para diferentes representações do produto.

Na minha opinião, você não pode dizer que o Abstract Factory Pattern é o irmão mais velho do Builder Pattern. SIM, ambos são padrões criacionais, mas a principal intenção dos padrões é totalmente diferente.

Janis
fonte
boa resposta, elaborar explicar.
towry
você pode explicar o que significa de "Separa a construção de um objeto complexo da sua representação"
Rajdeep
@ Rajdeep a explicação é longa para um comentário, é por isso que escrevi outra resposta.
Janis
@ Janis Onde é que essa resposta ou fonte de onde eu posso ler?
Rajdeep 9/0318
@Rajdeep eu recomendo que você leia o livro „Design Patterns“ - amazon.de/Patterns-Elements-Reusable-Object-Oriented-Software/…
Janis
7

Uma diferença marcante entre o Construtor e a fábrica que eu pude perceber foi a seguinte

suponha que temos um carro

class Car
{
  bool HasGPS;
  bool IsCityCar;
  bool IsSportsCar;
  int   Cylenders;
  int Seats;

  public:
     void Car(bool hasGPs=false,bool IsCityCar=false,bool IsSportsCar=false, int Cylender=2, int Seats=4);
 };

Na interface acima, podemos obter o carro da seguinte maneira:

 int main()
 {
    BadCar = new Car(false,false,true,4,4);
  }

mas e se, alguma exceção acontecer ao criar os assentos ??? VOCÊ NÃO OBTERÁ O OBJETO // // MAS

suponha que você tenha uma implementação como a seguinte

class Car
 {
    bool mHasGPS;
    bool mIsCityCar;
    bool mIsSportsCar;
    int mCylenders;
    int mSeats;

 public:
    void Car() : mHasGPs(false), mIsCityCar(false), mIsSportsCar(false), mCylender(2), mSeats(4) {}
    void SetGPS(bool hasGPs=false)  {mHasGPs = hasGPs;}
    void SetCity(bool CityCar)  {mIsCityCar = CityCar;}
    void SetSports(bool SportsCar)  {mIsSportsCar = SportsCar;}
    void SetCylender(int Cylender)  {mCylenders = Cylender;}    
    void SetSeats(int seat) {mSeats = seat;}    
};

 class CarBuilder 
 {
    Car* mCar;
public:
        CarBuilder():mCar(NULL) {   mCar* = new Car();  }
        ~CarBuilder()   {   if(mCar)    {   delete mCar;    }
        Car* GetCar()   {   return mCar; mCar=new Car();    }
        CarBuilder* SetSeats(int n) {   mCar->SetSeats(n); return this; }
        CarBuilder* SetCylender(int n)  {   mCar->SetCylender(n); return this;  }
        CarBuilder* SetSports(bool val) {   mCar->SetSports(val); return this;  }
        CarBuilder* SetCity(bool val)   {   mCar->SetCity(val); return this;    }
        CarBuilder* SetGPS(bool val)    {   mCar->SetGPS(val); return this; }
}

Agora você pode criar assim

 int main()
 {
   CarBuilder* bp =new CarBuilder;
    Car* NewCar  = bp->SetSeats(4)->SetSports(4)->SetCity(ture)->SetGPS(false)->SetSports(true)->GetCar();

     bp->SetSeats(2);

     bp->SetSports(4);

     bp->SetCity(ture);

     bp->SetSports(true)

     Car* Car_II=  bp->GetCar();

  }

Aqui no segundo caso, mesmo se uma operação falhar, você ainda obteria o carro.

Pode ser que o carro não funcione perfeitamente mais tarde, mas você teria o objeto.

Porque o Método de Fábrica fornece o Carro em uma única chamada, enquanto o Construtor constrói um por um.

Embora, isso depende das necessidades do reino para qual escolher.

Fooo
fonte
2
Certamente, é melhor não ter carro do que um carro inválido - e se você encontrar o problema apenas quando usar os intervalos?
Ken
@ Ken: Eu não estou insistindo que é um bom design a partir do projeto prospectivo de projeto comercial etc., a intenção de citar este exemplo para exemplificar a diferença entre os padrões. Definitivamente, você está certo de que isso é ruim pela experiência do usuário de comprar um carro ruim, mas, considere, existe uma fábrica na qual os carros são fabricados e alguma parte está com defeito, então o carro é produzido, mas com uma falha ruim que seria encontrada em o tempo de teste e envio desse carro para o cliente é interrompido.
Fooo
2
Gostaria de esclarecer que sou realmente um grande fã do padrão do construtor. No entanto, não pelo motivo que você deu. Um objeto inválido deve falhar na construção, quanto mais baixo for o processo de detecção de um bug, mais caro ele é. Com o padrão do construtor, seria normal para o método de construção (no seu exemplo chamado getCar ()) lançar uma exceção se houver algum dado necessário ausente.
Ken
7
+-------------------------------------------------------------------+---------------------------------------------------+
|                              Builder                              |                      Factory                      |
+-------------------------------------------------------------------+---------------------------------------------------+
| Return only single instance to handle complex object construction | Retrun various instances on multiple constructors |
| No interface required                                             | Interface driven                                  |
| Inner classes is involved (to avoid telescopic constructors)      | Subclasses are involved                           |
+-------------------------------------------------------------------+---------------------------------------------------+  

Padrão de construtor telescópico

Analogia:

  • Fábrica: 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.
  • Construtor: 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!" Assim, o construtor expõe os atributos que o objeto gerado deve ter, mas oculta como configurá-los.

Cortesia

Premraj
fonte
5

Builder e Abstract Factory são para diferentes propósitos. Dependendo do caso de uso correto, você deve selecionar o padrão de design adequado.

Recursos destacados do construtor :

  1. O padrão Builder cria um objeto complexo usando objetos simples e usando uma abordagem passo a passo
  2. Uma classe Builder cria o objeto final passo a passo. Este construtor é independente de outros objetos
  3. Substituição do método Factory / Abstract Factory neste cenário: Muitos argumentos para passar do programa cliente para a classe Factory que podem estar sujeitos a erros
  4. Alguns dos parâmetros podem ser opcionais, ao contrário do Factory, que força o envio de todos os parâmetros

Características principais da fábrica ( fábrica simples):

  1. Padrão criacional
  2. Baseado na herança
  3. Factory retorna um Método de Fábrica (interface) que, por sua vez, retorna Objeto Concreto
  4. É possível substituir novos objetos concretos pela interface e o cliente (responsável pela chamada) não deve estar ciente de todas as implementações concretas
  5. O cliente sempre acessa apenas a interface e você pode ocultar os detalhes da criação do objeto no método Factory.

Freqüentemente, os projetos começam usando o Factory Method (subclasses menos complicadas, mais personalizáveis ​​proliferam) e evoluem para Abstract Factory , Prototype ou Builder (mais flexível, mais complexo)

Dê uma olhada nas postagens relacionadas:

Mantendo o Construtor em Classe Separada (Interface Fluente)

Padrões de Design: Método Fábrica x Fábrica vs Fábrica Abstrata

Você pode consultar os artigos abaixo para obter mais detalhes:

criação

journaldev

Ravindra babu
fonte
5

Fábrica : Usado para criar uma instância de um objeto em que as dependências do objeto são mantidas inteiramente pela fábrica. Para o padrão abstrato de fábrica , geralmente existem muitas implementações concretas da mesma fábrica abstrata. A implementação correta da fábrica é injetada via injeção de dependência.

Construtor : Usado para construir objetos imutáveis , quando as dependências do objeto a ser instanciado são parcialmente conhecidas antecipadamente e parcialmente fornecidas pelo cliente do construtor.

Hamady C.
fonte
4

O padrão Abstract Factory & Builder são padrões criacionais, mas com intenções diferentes.

Abstract Factory Pattern enfatiza a criação de objetos para famílias de objetos relacionados, onde:

  • Cada família é um conjunto de classes derivadas de uma classe / interface base comum.
  • Cada objeto é retornado imediatamente como resultado de uma chamada.

O padrão do construtor se concentra na construção de um objeto complexo passo a passo. Separa a representação do processo de construção do objeto complexo, de modo que o mesmo processo de construção possa ser usado para diferentes representações.

  • O objeto Builder encapsula a configuração do objeto complexo.
  • O objeto Director conhece o protocolo de uso do Construtor, em que o protocolo define todas as etapas lógicas necessárias para construir o objeto complexo.
Saurabh Kumar
fonte
você pode explicar significado de "desacopla a representação do processo de construção do objeto complexo"
Rajdeep
3

Uma construção complexa é quando o objeto a ser construído é composto por diferentes outros objetos que são representados por abstrações.

Considere um menu no McDonald's. Um menu contém uma bebida, um prato principal e um lado. Dependendo de quais descendentes das abstrações individuais são compostos juntos, o menu criado possui outra representação.

  1. Exemplo: Cola, Big Mac, Batatas Fritas
  2. Exemplo: Sprite, Pepitas, Batatas Fritas

Lá, temos duas instâncias do menu com diferentes representações. O processo de construção, por sua vez, permanece o mesmo. Você cria um menu com uma bebida, um prato principal e um lado.

Usando o padrão do construtor, você separa o algoritmo de criação de um objeto complexo dos diferentes componentes usados ​​para criá-lo.

Em termos do padrão do construtor, o algoritmo é encapsulado no diretor, enquanto os construtores são usados ​​para criar as partes integrais. A variação do construtor usado no algoritmo do diretor resulta em uma representação diferente porque outras partes são compostas em um menu. A maneira como um menu é criado permanece o mesmo.

Janis
fonte
1
Isso explica a "separação de construção de objeto complexo da sua representação"
Rajdeep
2

A principal diferença entre eles é que o padrão Builder descreve principalmente a criação de objetos complexos passo a passo. No padrão Abstract Factory, a ênfase está nas famílias de objetos-produtos . O construtor retorna o produto na última etapa . Enquanto estiver no padrão Abstract Factory, o produto estará disponível imediatamente .

Exemplo: Digamos que estamos criando o Maze

1. Fábrica abstrata:

Maze* MazeGame::CreateMaze (MazeFactory& factory) {
Maze* maze = factory.MakeMaze(); /// product is available at start!!
 /* Call some methods on maze */
return maze;
}

2. Construtor:

Maze* MazeGame::CreateMaze (MazeBuilder& builder) {
builder.buildMaze(); /// We don't have access to maze
 /* Call some methods on builder */
return builder.GetMaze();
}
XYZCODE123
fonte
2

Acredito que o uso e a diferença entre os padrões do Factory & Builder possam ser entendidos / esclarecidos mais facilmente em um determinado período de tempo, enquanto você trabalhava na mesma base de código e nos requisitos de alteração.

Pela minha experiência, geralmente, você começa com um padrão de fábrica, incluindo alguns métodos estáticos de criador para ocultar principalmente a lógica de inicialização relativamente complexa. À medida que sua hierarquia de objetos se torna mais complexa (ou à medida que você adiciona mais tipos, parâmetros), você provavelmente acaba tendo seus métodos preenchidos com mais parâmetros e sem mencionar que precisará recompilar seu módulo Factory. Tudo isso, aumenta a complexidade dos métodos do seu criador, diminui a legibilidade e torna o módulo de criação mais frágil.

Esse ponto possivelmente será o ponto de transição / extensão. Ao fazer isso, você cria um módulo wrapper em torno dos parâmetros de construção e poderá representar novos objetos (semelhantes) adicionando mais abstrações (talvez) e implementações sem tocar na lógica de criação real. Então você teve uma lógica "menos" complexa.

Francamente, referir-me a algo como "ter um objeto criado em uma etapa ou várias etapas é a diferença", pois o único fator de diversidade não foi suficiente para eu distingui-las, pois eu poderia usar as duas maneiras em quase todos os casos que enfrentei. agora sem experimentar nenhum benefício. Então é isso que eu finalmente pensei sobre isso.

stdout
fonte
2

A principal vantagem do padrão do construtor sobre o padrão de fábrica é se você deseja criar algum objeto padrão com muitas personalizações possíveis, mas geralmente acaba personalizando apenas algumas.

Por exemplo, se você deseja gravar um cliente HTTP - você configurará alguns parâmetros padrão, como tempo limite de gravação / leitura padrão, protocolos, cache, DNS, interceptores, etc.

A maioria dos usuários do seu cliente usará apenas esses parâmetros padrão, enquanto outros usuários podem querer personalizar alguns dos outros parâmetros. Em alguns casos, você só deseja alterar os tempos limites e usar o restante, enquanto em outros casos pode ser necessário personalizar, por exemplo, o cache.

Aqui estão possíveis maneiras de instanciar seu cliente (extraído de OkHttpClient):

//just give me the default stuff
HttpClient.Builder().build()   

//I want to use custom cache
HttpClient.Builder().cache(MyCache()).build() 

//I want custom connection timeout
HttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).build() 

//I am more interested in read/write timeout
HttpClient.Builder()
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS).build()

Se você usar um padrão de fábrica para isso, acabará escrevendo muitos métodos com todas as combinações possíveis de parâmetros criacionais. Com o construtor, você apenas especifica aqueles de quem gosta e deixa que o construa para cuidar de todos os outros parâmetros.

daneejela
fonte
1

O padrão de construção enfatiza a complexidade da criação do objeto (resolvido por "etapas")

O padrão abstrato enfatiza "apenas" a "abstração" de objetos (múltiplos, mas relacionados).

Sandeep Jindal
fonte
1

A diferença está clara No padrão do construtor, o construtor criará um tipo específico de objeto para você. Você precisa dizer o que o construtor deve construir. No padrão de fábrica, usando a classe abstrata, você está construindo diretamente o objeto específico.

Aqui, a classe construtora atua como mediadora entre a classe principal e as classes de tipo específico. Mais abstração.

user2738678
fonte
1

Ambos são muito parecidos, mas se você tiver um grande número de parâmetros para criação de objeto, com alguns deles opcionais com alguns valores padrão, vá para o padrão Builder.

Praveen Kumar
fonte
1

Na minha humilde opinião

Builder é algum tipo de fábrica mais complexa.

Porém, no Builder, você pode instanciar objetos usando outras fábricas , necessárias para criar objetos finais e válidos.

Então, falando sobre a evolução dos "Padrões da Criação" por complexidade, você pode pensar dessa maneira:

Dependency Injection Container -> Service Locator -> Builder -> Factory
v.babak
fonte
1

Ambos os padrões vêm para a mesma necessidade: oculte de algum código de cliente a lógica de construção de um objeto complexo. Mas o que torna "complexo" (ou, às vezes, complica) um objeto? Principalmente, é devido a dependências, ou melhor, ao estado de um objeto composto por estados mais parciais. Você pode injetar dependências pelo construtor para definir o estado inicial do objeto, mas um objeto pode exigir muitas delas, algumas estarão em um estado inicial padrão (apenas porque deveríamos ter aprendido que definir uma dependência padrão como nula não é a maneira mais limpa ) e algum outro conjunto para um estado impulsionado por alguma condição. Além disso, existem propriedades de objetos que são algum tipo de "dependências inconscientes", mas também podem assumir estados opcionais.

existem duas maneiras bem conhecidas de dominar essa complexidade:

  • Composição / agregação: construa um objeto, construa seus objetos dependentes e, em seguida, conecte-os. Aqui, um construtor pode tornar transparente e flexível o processo que determina as regras que lideram a construção do componente.

  • Polimorfismo: as regras de construção são declaradas diretamente na definição de subtipo, portanto, você tem um conjunto de regras para cada subtipo e alguma condição decide qual delas dentre essas regras se aplica à construção do objeto. Uma fábrica se encaixa perfeitamente nesse cenário.

Nada impede misturar essas duas abordagens. Uma família de produtos pode abstrair a criação de objetos feita com um construtor, um construtor pode usar fábricas para determinar qual objeto componente é instanciado.

Carmine Ingaldi
fonte
0

Na minha opinião, o padrão Builder é usado quando você deseja criar um objeto a partir de vários outros objetos e a criação de peças precisa ser independente do objeto que você deseja criar. Ajuda a ocultar a criação de parte do cliente para tornar o construtor e o cliente independentes. É usado para criação de objetos complexos (objetos que podem consistir em propriedades complicadas)

Enquanto o padrão de fábrica especifica que você deseja criar objetos de uma família comum e deseja que ele seja processado de uma só vez. É usado para objetos mais simples.

AjayLohani
fonte
0

Construtor e fábrica abstrata

O padrão de design do Builder é muito semelhante, em certa medida, ao padrão Abstract Factory. É por isso que é importante poder fazer a diferença entre as situações em que uma ou outra é usada. No caso da Abstract Factory, o cliente usa os métodos da fábrica para criar seus próprios objetos. No caso do Builder, a classe Builder é instruída sobre como criar o objeto e, em seguida, é solicitada, mas a maneira como a classe é montada depende da classe Builder, esse detalhe fazendo a diferença entre os dois padrões.

Interface comum para produtos

Na prática, os produtos criados pelos construtores de concreto têm uma estrutura significativamente diferente; portanto, se não houver motivo para derivar produtos diferentes, uma classe-mãe comum. Isso também distingue o padrão Builder do padrão Abstract Factory, que cria objetos derivados de um tipo comum.

De: http://www.oodesign.com/builder-pattern.html

Arturas M
fonte
-2

O padrão de fábrica cria uma implementação concreta de uma classe em tempo de execução, ou seja, sua principal intenção é usar o polimorfismo para permitir que as subclasses decidam qual classe instanciar. Isso significa que, no tempo de compilação, não sabemos a classe exata que será criada, enquanto o padrão Builder se preocupa principalmente em resolver o problema de antipadrão de construtores telescópicos, o que surge devido a um grande número de campos opcionais de uma classe. No padrão construtor, não há noção de polimorfismo, pois sabemos qual objeto estamos tentando construir em tempo de compilação.

O único tema comum desses dois padrões é ocultar os construtores e a criação de objetos por trás dos métodos de fábrica e o método de compilação, para melhorar a construção dos objetos.

Saad
fonte
-2

O padrão de fábrica permite criar um objeto de uma só vez, enquanto o padrão do construtor permite interromper o processo de criação de um objeto. Dessa forma, você pode adicionar diferentes funcionalidades durante a criação de um objeto.

MrWaqasAhmed
fonte