Na maioria dos exemplos citados para o uso de Injeção de Dependência, também podemos resolver usando o padrão de fábrica. Parece que quando se trata de uso / design, a diferença entre injeção de dependência e fábrica é embaçada ou fina.
Uma vez alguém me disse que é como você o usa que faz a diferença!
Uma vez eu usei o StructureMap um contêiner de DI para resolver um problema; posteriormente, o redesenhei para trabalhar com uma fábrica simples e removi as referências ao StructureMap.
Alguém pode me dizer qual é a diferença entre eles e onde usar o que, qual é a melhor prática aqui?
dependency-injection
factory-pattern
design-patterns
Binoj Antony
fonte
fonte
Respostas:
Ao usar uma fábrica, seu código ainda é realmente responsável pela criação de objetos. Por DI, você terceiriza essa responsabilidade para outra classe ou estrutura, que é separada do seu código.
fonte
Manually-Injected Dependency
Eu sugeriria manter os conceitos claros e simples. A Injeção de Dependência é mais um padrão arquitetural para o acoplamento fraco de componentes de software. O padrão de fábrica é apenas uma maneira de separar a responsabilidade de criar objetos de outras classes para outra entidade. O padrão de fábrica pode ser chamado como uma ferramenta para implementar DI. A injeção de dependência pode ser implementada de várias maneiras, como DI usando construtores, mapeando arquivos xml etc.
fonte
Injeção de dependência
Em vez de instanciar as peças em si, um carro pede as peças que ele precisa para funcionar.
Fábrica
Une as peças para formar um objeto completo e oculta o tipo de concreto do chamador.
Resultado
Como você pode ver, Fábricas e DI se complementam.
Você se lembra de cachinhos dourados e dos três ursos? Bem, a injeção de dependência é assim. Aqui estão três maneiras de fazer a mesma coisa.
Exemplo # 1 - Esse é o pior porque oculta completamente a dependência. Se você olhasse o método como uma caixa preta, não teria idéia de que precisava de um carro.
Exemplo 2 - Isso é um pouco melhor, porque agora sabemos que precisamos de um carro, pois passamos em uma fábrica de carros. Mas desta vez estamos passando muito, já que todo o método realmente precisa é de um carro. Estamos passando em uma fábrica apenas para fabricar o carro quando o carro pode ser fabricado fora do método e passado.
Exemplo # 3 - Isso é ideal porque o método pede exatamente o que ele precisa. Nem muito nem pouco. Não preciso escrever um MockCarFactory apenas para criar o MockCars, posso passar o mock diretamente. É direto e a interface não mente.
Este Google Tech Talk, de Misko Hevery, é incrível e é a base do que eu deduzi meu exemplo. http://www.youtube.com/watch?v=XcT4yYu_TTs
fonte
A razão pela qual a Injeção de Dependência (DI) e os Padrões de Fábrica são semelhantes é porque são duas implementações do Inversion of Control (IoC), que é uma arquitetura de software. Simplificando, são duas soluções para o mesmo problema.
Portanto, para responder à pergunta, a principal diferença entre o padrão Factory e DI é como a referência do objeto é obtida. Com injeção de dependência, como o nome indica, a referência é injetada ou fornecida ao seu código. Com o padrão de fábrica, seu código deve solicitar a referência para que seu código busque o objeto. Ambas as implementações removem ou desacoplam a ligação entre o código e a classe ou o tipo subjacente da referência do objeto que está sendo usada pelo código.
Vale a pena notar que os padrões Factory (ou mesmo os padrões Abstract Factory que são fábricas que retornam novas fábricas que retornam referências a objetos) podem ser gravados para escolher dinamicamente ou vincular ao tipo ou classe de objeto solicitado em tempo de execução. Isso os torna muito semelhantes (ainda mais que o DI) ao padrão Service Locator, que é outra implementação da IoC.
O padrão de design da fábrica é bastante antigo (em termos de software) e existe há algum tempo. Desde a recente popularidade do padrão arquitetural IoC, ele está ressurgindo.
Eu acho que quando se trata de padrões de design de IoC: injetores injetam, localizadores localizam e as fábricas foram refatoradas.
fonte
Existem problemas que são fáceis de resolver com injeção de dependência que não são tão facilmente resolvidos com um conjunto de fábricas.
Algumas das diferenças entre, por um lado, inversão de controle e injeção de dependência (IOC / DI) e, por outro lado, um localizador de serviço ou um conjunto de fábricas (fábrica) são:
O IOC / DI é um ecossistema completo de objetos e serviços de domínio por si só. Ele define tudo para você da maneira que você especificar. Seus objetos e serviços de domínio são construídos pelo contêiner e não se constroem: portanto, eles não têm nenhuma dependência do contêiner ou de nenhuma fábrica. O IOC / DI permite um grau extremamente alto de configurabilidade, com toda a configuração em um único local (construção do contêiner) na camada superior da sua aplicação (a GUI, o front-end da Web).
O Factory abstrai uma parte da construção de seus objetos e serviços de domínio. Mas os objetos e serviços de domínio ainda são responsáveis por descobrir como se construir e como obter todas as coisas das quais dependem. Todas essas dependências "ativas" são filtradas por todas as camadas do seu aplicativo. Não há um único lugar para configurar tudo.
fonte
Uma desvantagem do DI é que ele não pode inicializar objetos com lógica. Por exemplo, quando eu preciso criar um personagem com nome e idade aleatórios, o DI não é a escolha do padrão de fábrica. Com as fábricas, podemos facilmente encapsular o algoritmo aleatório da criação do objeto, que suporta um dos padrões de design chamados "Encapsular o que varia".
fonte
De: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
fonte
Acredito que o DI seja um tipo de camada de abstração nas fábricas, mas elas também fornecem benefícios além da abstração. Uma verdadeira fábrica sabe como instanciar um único tipo e configurá-lo. Uma boa camada de DI fornece a capacidade, através da configuração, de instanciar e configurar vários tipos.
Obviamente, para um projeto com alguns tipos simples que requer lógica de negócios relativamente estável em sua construção, o padrão de fábrica é simples de entender, implementar e funcionar bem.
OTOH, se você tiver um projeto que contém vários tipos cujas implementações você espera alterar com frequência, o DI oferece a flexibilidade através de sua configuração para fazer isso em tempo de execução sem precisar recompilar suas fábricas.
fonte
Teoria
Há dois pontos importantes a serem considerados:
Quem cria objetos
Que tipo de objetos ele gerencia:
Exemplo prático de como usar injeção de fábrica e de dependência em um único projeto
Módulo de aplicativo para criação de pedidos que contém várias entradas chamadas linha de pedidos.
Vamos assumir que queremos criar a seguinte arquitetura de camada:
Objetos de domínio podem ser objetos armazenados no banco de dados. Repositório (DAO) ajuda na recuperação de objetos do banco de dados. O serviço fornece API para outros módulos. Permite operações no
order
móduloAs entidades que estarão no banco de dados são Order e OrderLine. O pedido pode ter vários OrderLines.
Agora vem parte importante do design. Os módulos fora deste devem criar e gerenciar OrderLines por conta própria? Não. A linha do pedido deve existir apenas quando você tiver um pedido associado. Seria melhor se você pudesse ocultar a implementação interna para classes externas.
Mas como criar um pedido sem o conhecimento dos OrderLines?
Fábrica
Alguém que deseja criar um novo pedido usou o OrderFactory (que oculta detalhes sobre o fato de como criamos o pedido).
É assim que parecerá dentro do IDE. Classes fora do
domain
pacote serão usadas emOrderFactory
vez do construtor dentroOrder
OrderRepository e OrderService são gerenciados pela estrutura de injeção de dependência. O repositório é responsável por gerenciar operações CRUD no banco de dados. O serviço injeta o Repositório e o utiliza para salvar / localizar as classes de domínio corretas.
fonte
[Factory]: Usually responsible for creation of stateful objects [Dependency Injections] More likely to create stateless objects
Eu não entendo o porquêSei que essa pergunta é antiga, mas gostaria de adicionar meus cinco centavos,
Eu acho que a injeção de dependência (DI) é, de várias maneiras, como um padrão de fábrica (FP) configurável e, nesse sentido, qualquer coisa que você possa fazer com o DI poderá fazê-lo com essa fábrica.
Na verdade, se você usar o Spring, por exemplo, terá a opção de autowiring resources (DI) ou fazer algo assim:
E então use essa instância 'mb' para fazer qualquer coisa. Não é uma ligação para uma fábrica que retornará uma instância?
A única diferença real que noto entre a maioria dos exemplos de FP é que você pode configurar o que "myBean" é em um xml ou em outra classe, e uma estrutura funcionará como a fábrica, mas, além disso, é a mesma coisa, e você certamente pode ter um Factory que leia um arquivo de configuração ou obtenha a implementação conforme necessário.
E se você me pede a minha opinião (e eu sei que não), acredito que o DI faz a mesma coisa, mas apenas acrescenta mais complexidade ao desenvolvimento, por quê?
bem, por um lado, para você saber qual é a implementação que está sendo usada para qualquer bean que você usa automaticamente com DI, você precisa acessar a própria configuração.
mas ... e a promessa de que você não precisará conhecer a implementação do objeto que está usando? pfft! a sério? quando você usa uma abordagem como esta ... você não é o mesmo que escreve a implementação? e mesmo que não o faça, você não fica quase o tempo todo olhando como a implementação faz o que deveria fazer?
e, por último, não importa o quanto uma estrutura DI prometa que você construa coisas dissociadas dela, sem dependências de suas classes, se você estiver usando uma estrutura, construa tudo ao seu redor, se precisar mudar a abordagem ou a estrutura, não será uma tarefa fácil ... NUNCA! ... mas, como você constrói tudo em torno dessa estrutura específica, em vez de se preocupar com qual é a melhor solução para o seu negócio, você enfrentará um grande problema ao fazer isso.
De fato, o único aplicativo de negócios real para uma abordagem FP ou DI que eu posso ver é se você precisar alterar as implementações usadas no tempo de execução , mas pelo menos as estruturas que conheço não permitem que você faça isso, você deve sair tudo perfeito na configuração no momento do desenvolvimento e, se você precisar, use outra abordagem.
Portanto, se eu tiver uma classe que tenha desempenho diferente em dois escopos no mesmo aplicativo (digamos, duas empresas de uma holding), tenho que configurar a estrutura para criar dois beans diferentes e adaptar meu código para usar cada um. Não é o mesmo que escrever apenas algo assim:
o mesmo que este:
E isto:
De qualquer forma, você terá que alterar algo em seu aplicativo, sejam classes ou arquivos de configuração, mas precisará realizá-lo e reimplementá-lo.
Não seria bom fazer algo assim:
Dessa forma, você define o código da fábrica para obter a implementação correta em tempo de execução, dependendo da empresa do usuário registrado? Agora isso seria útil. Você pode simplesmente adicionar um novo jar com as novas classes e definir as regras, talvez também em tempo de execução (ou adicionar um novo arquivo de configuração, se você deixar esta opção em aberto), sem alterações nas classes existentes. Esta seria uma fábrica dinâmica!
isso não seria mais útil do que ter que escrever duas configurações para cada empresa e talvez até ter dois aplicativos diferentes para cada uma?
Você pode me dizer que eu não preciso fazer a alternância no tempo de execução, portanto, eu configuro o aplicativo e, se eu herdar a classe ou usar outra implementação, basta alterar a configuração e reimplementar. Ok, isso também pode ser feito com uma fábrica. E seja honesto, quantas vezes você faz isso? talvez apenas quando você tiver um aplicativo que será usado em outro lugar da sua empresa e você passará o código para outra equipe, e eles farão coisas assim. Mas ei, isso também pode ser feito com a fábrica e seria ainda melhor com uma fábrica dinâmica !!
De qualquer forma, a seção de comentários está aberta para você me matar.
fonte
O COI é um conceito implementado de duas maneiras. Criação de dependência e injeção de dependência, Fábrica / Resumo de fábrica são o exemplo da criação de dependência. A injeção de dependência é construtora, configuradora e interface. O núcleo do COI é não depender das classes concretas, mas definir o resumo dos métodos (por exemplo, uma interface / classe abstrata) e usar esse resumo para chamar o método da classe concreta. Como padrão de fábrica, retorne a classe base ou interface. Injeção de dependência semelhante usa classe / interface base para definir valor para objetos.
fonte
Com a injeção de dependência, o cliente não precisa obter suas dependências por conta própria, tudo preparado com antecedência.
Com as fábricas, alguém precisa chamá-las para levar os objetos gerados para o local onde são necessários.
A diferença está principalmente nessa linha onde é feita a chamada da fábrica e a busca do objeto construído.
Mas com as fábricas, você deve escrever essa linha 1 em todos os lugares que precisar desse objeto. Com o DI, você só precisa criar a fiação (relação entre uso e objeto criado) uma vez e confiar na presença do objeto posteriormente em qualquer lugar. Por outro lado, o DI frequentemente requer um pouco mais de trabalho (quanto depende da estrutura) do lado da preparação.
fonte
Eu tive a mesma pergunta assim que li sobre DI e acabei neste post. Então, finalmente, é isso que eu entendi, mas, por favor, me corrija se estiver errado.
"Há muito tempo, havia pequenos reinos com seus próprios órgãos de governo controlando e tomando decisões com base em suas próprias regras escritas. Mais tarde, formou um grande governo eliminando todos esses pequenos órgãos de governo que têm um conjunto de regras (constituição) e são implementados pelos tribunais"
Os órgãos de governo dos pequenos reinos são "Fábricas"
O grande governo é o "Injetor de Dependências".
fonte
Você pode dar uma olhada neste link para comparar as duas abordagens (e outras) em um exemplo real.
Basicamente, quando os requisitos mudam, você acaba modificando mais código se usar fábricas em vez de DI.
Isso também é válido com o DI manual (ou seja, quando não há uma estrutura externa que forneça as dependências para seus objetos, mas você as transmite em cada construtor).
fonte
A maioria das respostas aqui explica a diferença conceitual e os detalhes de implementação de ambos. No entanto, não consegui encontrar explicações sobre a diferença na aplicação sobre a qual a IMO é a mais importante e o OP perguntou. Então, deixe-me reabrir este tópico ...
Exatamente. Em 90% dos casos, você pode obter referência de objeto usando Factory ou DI e, geralmente, acaba com o último. Em outros 10% dos casos, usar o Factory é a maneira correta . Esses casos incluem a obtenção de objetos por variável nos parâmetros de tempo de execução. Como isso:
Nesse caso,
client
não é possível obter DI (ou pelo menos requer uma solução alternativa feia). Portanto, como regra geral para tomar uma decisão: se uma dependência puder ser obtida sem nenhum parâmetro calculado em tempo de execução, o DI será preferido, caso contrário, use Factory.fonte
Eu acredito que o DI é uma maneira de configurações ou instanciar um bean. O DI pode ser feito de várias maneiras, como construtor, setter-getter etc.
O padrão de fábrica é apenas outra maneira de instanciar beans. esse padrão será usado principalmente quando você precisar criar objetos usando o padrão de design de fábrica, porque, ao usar esse padrão, você não configura as propriedades de um bean, apenas instancia o objeto.
Verifique este link: Injeção de Dependência
fonte
Binoj,
Eu não acho que você precise escolher um sobre o outro.
O ato de mover uma classe ou interface dependente para um construtor ou setter de classe segue o padrão DI. O objeto que você passa para o construtor ou conjunto pode ser implementado com o Factory.
Quando usar? Use o padrão ou padrões que estão na sua casa do leme do desenvolvedor. Com o que eles se sentem mais confortáveis e mais fáceis de entender.
fonte
Acredito que três aspectos importantes governam os objetos e seu uso:
1. Instanciação (de uma classe juntamente com a inicialização, se houver).
2. Injeção (da instância criada) onde for necessária.
3. Gerenciamento do ciclo de vida (da instância criada).
Usando o padrão de fábrica, o primeiro aspecto (instanciação) é alcançado, mas os dois restantes são questionáveis. A classe que usa outras instâncias deve codificar as fábricas (em vez de as instâncias serem criadas), o que dificulta a capacidade de acoplamento solto. Além disso, gerenciamento do ciclo de vidade instâncias torna-se um desafio em um aplicativo grande em que uma fábrica é usada em vários locais (principalmente, se a fábrica não gerencia o ciclo de vida da instância que retorna, fica feia).
Por outro lado, usando um DI (do padrão IoC), todos os 3 são abstraídos fora do código (para o contêiner DI) e o bean gerenciado não precisa de nada sobre essa complexidade. Acoplamento solto , um objetivo arquitetônico muito importante pode ser alcançado silenciosamente confortavelmente. Outro objetivo arquitetural importante, a separação de preocupações pode ser alcançada muito melhor do que as fábricas.
Enquanto as fábricas podem ser adequadas para pequenas aplicações, as maiores seriam melhores para escolher o DI do que as fábricas.
fonte
Meus pensamentos:
Injeção de Dependência: passe colaboradores como parâmetros para os construtores. Estrutura de injeção de dependência: uma fábrica genérica e configurável para criar os objetos a serem passados como parâmetros para os construtores.
fonte
Uma estrutura de injeção é uma implementação do padrão de fábrica.
Tudo depende de suas necessidades. Se você precisar implementar o padrão de fábrica em um aplicativo, é muito provável que seus requisitos sejam atendidos por uma das inúmeras implementações de estruturas de injeção existentes.
Você só deve implementar sua própria solução se seus requisitos não puderem ser atendidos por nenhuma das estruturas de terceiros. Quanto mais código você escreve, mais você precisa manter. Código é um passivo, não um ativo.
Os argumentos sobre qual implementação você deve usar não são tão importantes quanto entender as necessidades de arquitetura do seu aplicativo.
fonte
Padrão de Design de Fábrica
O padrão de design da fábrica é caracterizado por
Você pode observar algumas coisas quando se pergunta como abaixo
Estes são tratados por injeção de dependência.
Injeção de dependência
Você pode ter maneiras diferentes de injetar dependência. Para simplificar, vamos com a injeção de interface
No DI, o contêiner cria as instâncias necessárias e as "injeta" no objeto.
Assim, elimina a instanciação estática.
Exemplo:
fonte
De um valor nominal, eles parecem iguais
Em termos muito simples, o Padrão de Fábrica, um Padrão de Criação ajuda a criar um objeto para nós - "Definir uma interface para criar um objeto". Se tivermos um tipo de pool de objetos com valor-chave (por exemplo, Dicionário), passando a chave para a Factory (refiro-me ao Simple Factory Pattern), você poderá resolver o Type. Tarefa concluída! O Framework de Injeção de Dependência (como Mapa de Estrutura, Ninject, Unity ... etc), por outro lado, parece estar fazendo a mesma coisa.
Mas ... "Não reinvente a roda"
Do ponto de vista arquitetônico, é uma camada vinculativa e "Não reinvente a roda".
Para um aplicativo de nível corporativo, o conceito de DI é mais uma camada arquitetural que define dependências. Para simplificar ainda mais, você pode pensar nisso como um projeto separado da biblioteca de classes, que resolve a dependência. A principal aplicação depende deste projeto, em que o resolvedor de dependências se refere a outras implementações concretas e à resolução de dependências.
Além de "GetType / Create" de uma fábrica, na maioria das vezes precisamos de mais recursos (capacidade de usar XML para definir dependências, zombaria e testes de unidade etc.). Desde que você se referiu ao Mapa da Estrutura, consulte a lista de recursos do Mapa da Estrutura . É claramente mais do que simplesmente resolver um mapeamento simples de objetos. Não reinvente a roda!
Se tudo que você tem é um martelo, tudo parece um prego
Dependendo dos seus requisitos e do tipo de aplicativo que você cria, você precisa fazer uma escolha. Se tiver apenas alguns projetos (pode ser um ou dois ..) e envolver poucas dependências, você poderá escolher uma abordagem mais simples. É como usar o acesso a dados do ADO .Net sobre o Entity Framework para chamadas simples de um ou dois bancos de dados, onde a introdução do EF é um exagero nesse cenário.
Mas, para um projeto maior ou se seu projeto aumentar, eu recomendo que você tenha uma camada de DI com uma estrutura e dê espaço para alterar a estrutura de DI que você usa (use uma fachada no aplicativo principal (Web App, Web API, desktop ..etc.).
fonte
Com uma fábrica, você pode agrupar interfaces relacionadas. Portanto, se os parâmetros passados podem ser agrupados em uma fábrica, também é uma boa solução para
constructor overinjection
examinar este código *):Olhe para o construtor, você só precisa passar o
IAddressModelFactory
lá, menos parâmetros *):Você vê em
CustomerController
muitos parâmetros passados. Sim, você pode ver isso,constructor overinjection
mas é assim que o DI funciona. E não há nada errado com oCustomerController
.*) O código é do nopCommerce.
fonte
Em termos simples, o método Injeção de Dependência vs Fábrica implica um mecanismo de push versus pull, respectivamente.
Mecanismo de tração : a classe indiretamente depende do método Factory, que por sua vez depende das classes concretas.
Mecanismo de pressão : O componente raiz pode ser configurado com todos os componentes dependentes em um único local, promovendo assim alta manutenção e acoplamento solto.
Com o método Factory, a responsabilidade ainda recai sobre a classe (embora indiretamente) para criar um novo objeto, onde, como na injeção de dependência, essa responsabilidade é terceirizada (ao custo de vazar a abstração)
fonte
Eu acho que estas são ortogonais e podem ser usadas juntas. Deixe-me mostrar um exemplo que me deparei recentemente no trabalho:
Estávamos usando a estrutura Spring em Java para DI. Uma classe singleton (
Parent
) teve que instanciar novos objetos de outra classe (Child
), e esses tinham colaboradores complexos:Neste exemplo,
Parent
precisa receberDepX
instâncias apenas para passá-las aoChild
construtor. Problemas com isso:Parent
tem mais conhecimento doChild
que deveriaParent
tem mais colaboradores do que deveriaChild
envolve a alteraçãoParent
Foi quando percebi que um
Factory
se encaixaria aqui perfeitamente:Child
classe, como visto porParent
Child
, que pode ser centralizado na configuração do DI.Esta é a
Parent
classe simplificada e aChildFactory
classe:fonte
Você usa injeção de dependência quando sabe exatamente que tipo de objetos você precisa neste momento. Enquanto no caso do padrão de fábrica, você apenas delega o processo de criação de objetos para a fábrica, pois não sabe ao certo o tipo exato de objetos que precisa.
fonte
Uso os dois para criar uma estratégia de Inversão de controle com mais legibilidade para desenvolvedores que precisam mantê-la depois de mim.
Eu uso um Factory para criar meus diferentes objetos de Camada (Negócios, Acesso a Dados).
Outro desenvolvedor verá isso e, ao criar um objeto Business Layer, ele procura no BusinessFactory e Intellisense fornece ao desenvolvedor todas as camadas de negócios possíveis para criar. Não precisa jogar, encontre a interface que eu quero criar.
Essa estrutura já é Inversão de controle. Não sou mais responsável por criar o objeto específico. Mas você ainda precisa garantir a injeção de dependência para poder mudar as coisas facilmente. Criar sua própria injeção de dependência personalizada é ridículo, então eu uso o Unity. Dentro do CreateCarBusiness (), peço ao Unity que resolva qual classe pertence a isso e sua vida útil.
Portanto, minha estrutura de injeção de dependência de fábrica de código é:
Agora eu tenho o benefício de ambos. Meu código também é mais legível para outros desenvolvedores quanto aos escopos dos meus objetos que eu uso, em vez da Injeção de Dependência do Construtor, que diz apenas que todo objeto está disponível quando a classe é criada.
Eu uso isso para alterar meu acesso a dados do banco de dados para uma camada de acesso a dados codificada personalizada ao criar testes de unidade. Não quero que meus testes de unidade se comuniquem com bancos de dados, servidores da web, servidores de e-mail etc. Eles precisam testar minha camada de negócios porque é aí que está a inteligência.
fonte
Usar injeção de dependência é muito melhor na minha opinião, se você estiver: 1. implantando seu código em uma pequena partição, porque ele lida bem com a dissociação de um código grande. 2. testability é um dos casos em que o DI pode ser usado porque você pode simular facilmente os objetos não dissociados. com o uso de interfaces, você pode facilmente zombar e testar cada objeto. 3. você pode revisar simultaneamente cada parte do programa sem precisar codificar a outra parte, uma vez que esta é desacoplada.
fonte