Por que o padrão de design do método de fábrica é mais útil do que ter classes e chamá-las individualmente?

32

Nos padrões de design "Gang of Four", há o método Factory:

class Factory(product)
  case product
  when a
    new A
  when b
    new B
  when c
    new C
end

new Factory(a)

Por que isso é mais útil do que ter três classes, a, b, e ce chamá-los individualmente?

alt
fonte
1
O que você quer dizer com precisão? Por que não instanciar todos os três? É isso que você quer dizer?
Neil
1
@ Neil Não, no padrão de fábrica, todas as classes existem como irmãos. Por que ligar para a fábrica para acessar indiretamente as classes a, b, c?
alt
3
na verdade, isso não parece o padrão do método de fábrica para mim, se é que está mais próximo da fábrica abstrata
jk.
2
Porque no momento do design, você não sabe qual das três classes precisa instanciar.
MrWhite
2
@jk: Não, realmente não. programmers.stackexchange.com/questions/81838/…
pdr

Respostas:

54

Porque o seu exemplo não é complicado o suficiente. Para um cenário tão simples, nem faz sentido usar um padrão avançado.

Mas se você precisa saber mais do que o produto para construir A, B ou C e não pode ter acesso direto a esse conhecimento, é útil. Então você está usando a fábrica para atuar como um centro de conhecimento para produzir os objetos necessários.

Talvez esses objetos precisem de uma referência a algum objeto X, que a fábrica pode fornecer, mas seu código no local em que você deseja construir A, B ou C não pode ou não deve ter acesso a X. Talvez quando você tiver X você cria A e B, mas se você tem o tipo Y, cria C.

Considere também que alguns objetos podem precisar de 20 dependências para criar; o que então? Ir procurar essas dependências em um local onde elas não deveriam estar acessíveis pode ser problemático.

Mateusz
fonte
13
+1 por deixar claro que o padrão de fábrica nem sempre é a melhor abordagem.
911 Neil
1
Porque o seu exemplo não é complicado o suficiente. Para um cenário tão simples, nem faz sentido usar um padrão avançado. Então, o que você faria neste caso? Inline a construção condicional?
PDR
Pode ser apenas um método que pega o produto e retorna o que você precisa para torná-lo reutilizável, para que ele não precise estar alinhado. Se esse método crescer em algo maior ou for usado em várias outras classes, você poderá refatorá-lo para outra classe.
Mateusz
O padrão é chamado de Método de Fábrica por um motivo. O método não precisa estar em uma classe diferente para ser um Método de Fábrica (embora geralmente seja).
P6
Eu perdi o "Método" nele, então você está certo, senhor.
Mateusz
23

Um padrão de fábrica é geralmente mais complexo que isso. Uma fábrica decide em determinados critérios qual instância criar / devolver. Em vez disso, quando você não usa a fábrica, o código é usado repetidamente em vários locais do seu código.

Como exemplo, considere o seguinte: você precisa carregar dados de um banco de dados, mas você tem um banco de dados central para integração com muitos dados e um menor na memória em cada dev-PC. No seu código, você solicita que uma fábrica obtenha um identificador de banco de dados e a fábrica retorna uma delas dependendo, por exemplo, de um arquivo de configuração.

Andy
fonte
20

O padrão Factory Method abstrai o processo de tomada de decisão da classe de chamada. Isso tem várias vantagens:

Reuso. Se eu quero instanciar em muitos lugares, não preciso repetir minha condição; portanto, quando adiciono uma nova classe, não corro o risco de perder uma.

Testabilidade unitária. Posso escrever 3 testes para a fábrica, para garantir que ele retorne os tipos corretos nas condições corretas, então minha classe de chamada precisa ser testada para ver se chama a fábrica e os métodos necessários na classe retornada. Ele não precisa saber nada sobre a implementação da própria fábrica ou sobre as classes de concreto.

Extensibilidade. Quando alguém decide que precisamos adicionar uma nova classe D a esta fábrica, nenhum código de chamada, nem testes de unidade ou implementação, precisa ser informado. Simplesmente criamos uma nova classe D e estendemos nosso método de fábrica. Esta é a própria definição de Princípio Aberto-Fechado .

Você pode até criar uma nova classe de fábrica e transformá-la em hot-swap, se a situação exigir - por exemplo, se você quiser ativar e desativar a classe D durante o teste. Encontrei essa situação apenas uma vez, mas foi extremamente útil.

Como já foi dito, o Padrão de Fábrica nem sempre é o caminho a percorrer. Mas, sempre que vir instanciação condicional, você deve pensar um pouco.

pdr
fonte
14

As principais vantagens do padrão de fábrica são duas:

  1. Os locais que precisam de uma implementação do produto não precisam saber como construí-lo. A fábrica mantém essa informação.

    Deseja saber quais argumentos passar para o construtor específico? Ou quais dependências você deve injetar? Ou como registrar a classe de implementação no banco de dados após sua configuração completa? Não? Deixe a fábrica cuidar de tudo isso.

  2. Os locais que precisam de uma implementação do produto não precisam saber no momento da descrição do módulo (ou seja, no momento da compilação) qual é o nome da classe de implementação.

    Portanto, anão precisa ter nada a ver com A; o "o que construir" pode ser descrito em termos das propriedades não funcionais desejadas, e não apenas no nome. Isso é muito mais flexível.

A desvantagem é que, onde você sabe o que fazer e como fazê-lo, obtém mais complexidade ao usar uma fábrica. A solução é simples: não use uma fábrica quando não fizer sentido!

Donal Fellows
fonte
2

Eu gostaria de pensar em padrões de design em termos de classes serem 'pessoas', e padrões são maneiras pelas quais as pessoas conversam entre si.

Então, para mim, o padrão de fábrica é como uma agência de contratação. Você tem alguém que precisará de um número variável de trabalhadores. Essa pessoa pode saber algumas informações de que precisa nas pessoas que contrata, mas é isso.

Portanto, quando precisam de um novo funcionário, ligam para a agência contratada e dizem o que precisam. Agora, para contratar alguém, você precisa conhecer muitas coisas - benefícios, verificação de elegibilidade etc. Mas a pessoa que contrata não precisa saber nada disso - a agência de contratação lida com tudo isso.

Da mesma forma, o uso de uma fábrica permite que o consumidor crie novos objetos sem precisar saber os detalhes de como eles são criados ou quais são suas dependências - eles só precisam fornecer as informações que realmente desejam.

Cortesia

Premraj
fonte
1

O padrão de fábrica é o padrão de design mais usado e abusado.

Eu me deparei com vários casos em que uma classe Factory é codificada quando um construtor simples seria adequado.

Não use uma classe de fábrica, a menos que: -

  • Você depende de um recurso externo, mas ainda não sabe exatamente qual.
  • A construção é cara e você deseja construir uma vez e reutilizar várias vezes.
  • A construção de uma nova instância depende de quais instâncias já foram construídas (por exemplo, você pode ter apenas cinco conexões ou você deve usar um número de identificação de conexão mais um que o último número usado).
James Anderson
fonte
0

Use o Método de Fábrica ao instanciar uma subclasse e o código do cliente não deve ser responsável por decidir qual subclasse específica é instanciada.

É útil porque impede que você precise alterar o código do cliente quando precisar alterar qual classe é instanciada. Alterar o código existente é uma prática ruim, porque geralmente é propenso a erros.

Um exemplo seria ter subclasses, em que cada uma classifica os dados em ordem crescente, mas de uma maneira diferente. Cada maneira é ideal para um tipo específico de dados. por exemplo: dados parcialmente classificados, dados que são números etc. O código do cliente é uma classe que lida apenas com a impressão de dados. Ter um código que decida qual classe de classificação é instanciada na classe cliente tornaria uma classe complexa. Em outras palavras, tendo mais de uma responsabilidade, nesse caso, decidir qual classe de classificação é ideal e imprimir dados. Ao colocar o código que decide qual classe de classificação é instanciada em uma classe Factory, ele separa as preocupações, para que você não precise alterar a classe cliente sempre que precisar alterar qual subclasse de classificação é instanciada.

É uma maneira de encobrir sua bunda, se você pode prever suas próprias mudanças na forma como ou qual classe é instanciada, as classes de fábrica fazem sentido usar. Isso ajuda a manter suas classes focadas em sua única responsabilidade e, como resultado, garante que você tenha menos chances de modificar o código existente que não está relacionado.

kiwicomb123
fonte