sem injeção de dependência

no exemplo Java a seguir, A classe cliente contém uma variável de membro de serviço que é inicializada pelo construtor do cliente. O cliente controla a implementação do serviço e controla a sua construção. Nesta situação, diz-se que o cliente tem uma dependência em código rígido do serviço de examples.

// An example without dependency injectionpublic class Client { // Internal reference to the service used by this client private ExampleService service; // Constructor Client() { // Specify a specific implementation in the constructor instead of using dependency injection service = new ExampleService(); } // Method within this client that uses the services public String greet() { return "Hello " + service.getName(); }}

injeção de dependência é uma técnica alternativa para inicializar a variável membro ao invés de explicitamente criar um objeto de serviço como mostrado acima., Podemos ajustar este exemplo usando as várias técnicas descritas e ilustradas nas subsecções abaixo.

tipos de dependência injectionEdit

Existem pelo menos três formas de um objecto cliente receber uma referência a um módulo externo:

injecção Construtora as dependências são fornecidas através de um construtor de classe do cliente. setter injeção o cliente expõe um método setter que o injector usa para injetar a dependência. injeção de interface a interface de dependência fornece um método de injeção que irá injetar a dependência em qualquer cliente passado a ele., Os clientes devem implementar uma interface que expõe um método setter que aceita a dependência. é possível que outros tipos de injecção para além dos acima apresentados.os quadros de ensaio podem também utilizar outros tipos. Alguns quadros de testes modernos nem sequer exigem que os clientes aceitem ativamente a injeção de dependência, tornando assim o código legacy testável. Em particular, na Linguagem Java, é possível usar a reflexão para tornar públicos atributos privados ao testar e, assim, aceitar injeções por atribuição.,

algumas tentativas de inversão do controle não fornecem a remoção completa da dependência, mas simplesmente substituir uma forma de dependência por outra. Como regra geral, se um programador pode olhar para nada além do Código do cliente e dizer que framework está sendo usado, então o cliente tem uma dependência hard-coded no framework.

Constructor injectionEdit

este método requer que o cliente forneça um parâmetro em um construtor para a dependência.

Setter injectionEdit

este método requer que o cliente forneça um método setter para a dependência.,

Interface injectionEdit

isto é simplesmente o cliente publicando uma interface de papel para os métodos setter das dependências do cliente. Pode ser usado para estabelecer como o injector deve falar com o cliente quando injectar dependências.

// Service setter interface.public interface ServiceSetter { public void setService(Service service);}// Client classpublic class Client implements ServiceSetter { // Internal reference to the service used by this client. private Service service; // Set the service that this client is to use. @Override public void setService(Service service) { this.service = service; }}

Construtor de injeção comparisonEdit

o Preferido quando todas as dependências podem ser construídos em primeiro lugar, porque ele pode ser usado para garantir que o objeto cliente está sempre em um estado válido, ao contrário de ter alguns dos seus dependência referências de ser nulo (não definido)., No entanto, por si só, falta-lhe flexibilidade para que as suas dependências sejam alteradas mais tarde. Este pode ser um primeiro passo para tornar o cliente imutável e, portanto, thread seguro.

Setter injection comparisonEdit

requer que o cliente forneça um método setter para cada dependência. Isto dá a liberdade de manipular o estado das referências de dependência a qualquer momento. Isso oferece flexibilidade, mas se houver mais de uma dependência a ser injetada, é difícil para o cliente garantir que todas as dependências sejam injetadas antes que o cliente possa ser fornecido para uso.,como estas injecções acontecem de forma independente, não há maneira de saber quando o injector termina a ligação ao cliente. Uma dependência pode ser deixada nula simplesmente pelo injetor não chamando seu setter. Isto obriga a verificar se a injecção foi concluída a partir do momento em que o cliente é montado para sempre que é utilizada.

Interface injection comparisonEdit

a vantagem da interface injection é que as dependências podem ser completamente ignorantes dos seus clientes, mas ainda podem receber uma referência a um novo cliente e, usando-o, enviar uma referência a si mesmo de volta para o cliente., Desta forma, as dependências tornam-se injetores. A chave é que o método de injeção (que pode ser apenas um método clássico de setter) é fornecido através de uma interface.

um montador ainda é necessário para introduzir o cliente e suas dependências. O montador tomaria uma referência ao cliente, lançá-la-ia para a interface setter que define essa dependência, e passá-la-ia para aquele objeto de dependência que daria a volta e passaria uma referência a si mesmo de volta para o cliente.,

para que a injecção de interface tenha valor, a dependência deve fazer algo além de simplesmente passar para trás uma referência a si mesma. Isto poderia estar agindo como uma fábrica ou sub-montador para resolver outras dependências, abstraindo alguns detalhes do montador principal. Pode ser a contagem de referência para que a dependência saiba quantos clientes estão a usá-la. Se a dependência mantiver uma coleção de clientes, ele poderia mais tarde injectá-los todos com uma instância diferente de si mesmo.,

montar examplesEdit

montar manualmente, principalmente à mão, é uma forma de implementar a injecção de dependência.

o exemplo acima constrói o gráfico de objetos manualmente e então invoca-o em um ponto para começar a funcionar. É importante notar que este injector não é puro. Usa um dos objectos que constrói. Ele tem uma relação puramente de construção-apenas com ExampleService, mas mistura a construção e uso do cliente. Isto não deve ser comum. No entanto, é inevitável., Assim como o software orientado a objetos precisa de um método estático não orientado a objetos como main() para começar, um grafo de objeto injectado dependência precisa de pelo menos um (de preferência apenas um) ponto de entrada para começar a coisa toda.

a construção Manual no método principal pode não ser esta reta para a frente e pode envolver construtores de chamadas, fábricas, ou outros padrões de construção também. Isto pode ser bastante avançado e abstrato., A linha é cruzada da injeção manual de dependências para a injeção de dependências de framework uma vez que o código de construção não é mais personalizado para a aplicação e é, em vez disso, universal.Frameworks como o Spring podem construir esses mesmos objetos e conectá-los antes de retornar uma referência ao cliente. Toda a Menção do concreto ExampleService pode ser movida do código para os dados de configuração.Frameworks como a Primavera permitem externalizar os detalhes da montagem em arquivos de configuração.Este código (acima) constrói objetos e os fios juntos de acordo com o feijão.xml (abaixo)., ExampleService ainda é construído, apesar de apenas ser mencionado abaixo. Um grafo objeto longo e complexo pode ser definido desta forma e a única classe mencionada no código seria aquela com o método do ponto de entrada, que neste caso é greet().

no exemplo acima cliente e serviço não tiveram que passar por quaisquer alterações a serem fornecidas até a Primavera. Eles são autorizados a permanecer simples POJOs. Isto mostra como a primavera pode conectar serviços e clientes que são completamente ignorantes de sua existência. Isto não poderia ser dito se as anotações da Primavera fossem adicionadas às classes., Ao manter anotações específicas de primavera e chamadas de se espalhar entre muitas classes, o sistema permanece vagamente dependente da Primavera. Isto pode ser importante se o sistema pretende sobreviver à Primavera.

a escolha de manter POJOs puros não vem sem custo. Ao invés de gastar o esforço para desenvolver e manter arquivos de configuração complexos, é possível simplesmente usar anotações para marcar classes e deixar a Primavera fazer o resto do trabalho. Resolver dependências pode ser simples se elas seguem uma convenção como a correspondência por tipo ou pelo nome. Isto é escolher convenção em vez de configuração., É também discutível que, ao refactorar outro quadro, remover anotações específicas de framework seria uma parte trivial da tarefa e muitas anotações de injeção são agora padronizadas.

@Componentpublic class ExampleService { public String getName() { return "World!"; }}

Assembly comparisonEdit

as diferentes implementações de injetores (fábricas, localizadores de serviço e recipientes de injeção de dependência) não são tão diferentes quanto a injeção de dependência. O que faz toda a diferença é onde eles podem ser usados., Mover chamadas para uma fábrica ou um localizador de serviço fora do cliente e para main e de repente main faz um recipiente de injeção de dependência bastante bom.ao mover todo o conhecimento do injector para fora, um cliente limpo, livre do conhecimento do mundo exterior, é deixado para trás. No entanto, qualquer objeto que usa outros objetos pode ser considerado um cliente. O objeto que contém main não é exceção. Este objecto principal não está a usar a injecção de dependência. Ele está realmente usando o padrão de localizador de serviço. Isto não pode ser evitado porque a escolha de implementações de serviço deve ser feita em algum lugar.,a externalização das dependências nos ficheiros de configuração não altera este facto. O que torna esta realidade parte de um bom design é que o localizador de serviço não é espalhado por toda a base de código. Limita-se a um local por pedido. Isso deixa o resto da base de código livre para usar injeção de dependência para fazer clientes limpos.

injeção de Dependência PatternEdit

os exemplos até agora têm sido exemplos excessivamente simples sobre a construção de uma string., No entanto, o padrão de injeção de dependência é mais útil ao construir um gráfico de objetos onde os objetos se comunicam através de mensagens. Os objetos construídos em main durarão para a vida do programa. O padrão típico é construir o grafo e, em seguida, chamar um método em um objeto para enviar o fluxo de controle para o grafo objeto. Assim como principal é o ponto de entrada para o código estático, este método é o ponto de entrada para as aplicações código não estático.,

AngularJS exampleEdit

Em AngularJS quadro, só há três maneiras de um componente (ou objeto de função) pode acessar diretamente suas dependências:

  1. O componente pode criar a dependência, geralmente usando o new operador.
  2. o componente pode procurar a dependência, referindo-se a uma variável global.
  3. o componente pode ter a dependência passada para ele onde é necessário.

As duas primeiras opções de criar ou procurar dependências não são óptimas porque codificam a dependência do componente., Isso torna difícil, se não impossível, modificar as dependências. Isto é especialmente problemático em testes, onde é frequentemente desejável fornecer dependências simuladas para o isolamento de testes.

a terceira opção é a mais viável, uma vez que remove a responsabilidade de localizar a dependência do componente. A dependência é simplesmente entregue ao componente.

No exemplo acima, SomeClass não está preocupado com a criação ou localizar o greeter de dependência, é simplesmente entregue o recepcionista quando é instanciado.,

isto é desejável, mas coloca a responsabilidade de obter a dependência do código que constrói SomeClass.

para gerenciar a responsabilidade da criação de dependência, cada aplicação AngularJS tem um injector. O injector é um localizador de serviço que é responsável pela construção e pesquisa de dependências.

Aqui está um exemplo de usar o serviço de injeção:

crie um novo injector que pode fornecer componentes definidos no myModule e solicite o nosso serviço de saudação do injector., (Isto é geralmente feito automaticamente pelo AngularJS bootstrap).

var injector = angular.injector();var greeter = injector.get('greeter');

pedir dependências resolve a questão da codificação difícil, mas também significa que o injector precisa ser passado ao longo da aplicação. Passar o injector viola a Lei de Demeter., Para remediar isso, utilizamos uma declarativa notação em nossos modelos em HTML, para entregar a responsabilidade de criação de componentes para o injector, como no exemplo:

<div ng-controller="MyController"> <button ng-click="sayHello()">Hello</button></div>
function MyController($scope, greeter) { $scope.sayHello = function() { greeter.greet('Hello World'); };}

Quando AngularJS compila o HTML, ele processa o ng-controller directiva, que por sua vez solicita o injector para criar uma instância do controlador e de suas dependências.

injector.instantiate(MyController);

isto é tudo feito nos bastidores., Como o id

defers to the injector to instantiate the class, it can satisfy all of the dependencies ofMyController without the controller ever knowing about the injector. O código da aplicação simplesmente declara as dependências de que necessita, sem ter que lidar com o injector. Esta configuração não infringe a Lei de Demeter.

C#Edite

exemplo da injecção do construtor, da injecção de Setter e da injecção da Interface em C#

Articles

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *