O que é Injeção de Dependência?
A Injeção de Dependência (DI) é um padrão de projeto no qual um objeto recebe outras instâncias das quais depende, em vez de criá-las internamente. Em vez de um componente buscar ativamente suas dependências, o framewokr as fornece de forma externa.
Esse padrão promove baixo acoplamento, facilitando a manutenção e os testes, já que os componentes dependem de abstrações e não de implementações concretas.
O AngularJS oferece um sistema robusto de DI. Os principais componentes utilizados para essa finalidade são:
- value
- factory
- service
- provider
- constant
Value
Um vallue é um objeto JavaScript simples usado para transmitir dados para controllers ou outros componentes durante a fase de configuração.
// Declaração do módulo
var app = angular.module("appPrincipal", []);
// Criação de um objeto value
app.value("valorPadrao", 10);
// Injeção do value em um controller
app.controller('CalculadoraController', function($scope, ServicoCalculo, valorPadrao) {
$scope.numero = valorPadrao;
$scope.resultado = ServicoCalculo.quadrado($scope.numero);
$scope.calcularQuadrado = function() {
$scope.resultado = ServicoCalculo.quadrado($scope.numero);
};
});
Factory
Uma factory é uma função que retorna um valor. É utilizada para criar objetos, computar dados ou executar lógica antes de fornecer o resultado.
// Definição do módulo
var app = angular.module("appPrincipal", []);
// Criação de uma factory para multiplicação
app.factory('ServicoMultiplicacao', function() {
var servico = {};
servico.multiplicar = function(a, b) {
return a * b;
};
return servico;
});
// Injeção da factory em um service
app.service('ServicoCalculo', function(ServicoMultiplicacao) {
this.quadrado = function(valor) {
return ServicoMultiplicacao.multiplicar(valor, valor);
};
});
Provider
O provider é uma forma mais flexível de criar services, factories ou outros componentes. Ele deve expor um método $get que retorna o objeto desejado. É a única forma de ser usado na fase de configuração (config) da aplicação.
// Módulo principal
var app = angular.module("appPrincipal", []);
// Configuração usando provider
app.config(function($provide) {
$provide.provider('ServicoMultiplicacao', function() {
this.$get = function() {
var servico = {};
servico.multiplicar = function(a, b) {
return a * b;
};
return servico;
};
});
});
Constant
Uma constant é usada para armazenar valores imutáveis que devem estar disponíveis durante toda a aplicação, inclusive na fase de confiugração.
app.constant("configuracaoApp", "valor constante");
Exemplo Prático
O exemplo abaixo demonstra a utilização de value, factory, service, provider e constant em uma única aplicação.
<html>
<head>
<meta charset="utf-8">
<title>Injeção de Dependência - AngularJS</title>
</head>
<body>
<h2>Exemplo de Injeção de Dependência</h2>
<div ng-app="appPrincipal" ng-controller="CalculadoraController">
<p>Digite um número: <input type="number" ng-model="numero" /></p>
<button ng-click="calcularQuadrado()">Quadrado</button>
<p>Resultado: {{resultado}}</p>
</div>
<script src="angular-1.4.6.js"></script>
<script>
var app = angular.module("appPrincipal", []);
// Provider para multiplicação
app.config(function($provide) {
$provide.provider('ServicoMultiplicacao', function() {
this.$get = function() {
var servico = {};
servico.multiplicar = function(a, b) {
return a * b;
};
return servico;
};
});
});
// Value com valor padrão
app.value("valorPadrao", 5);
// Factory (redefinindo, apenas para demonstração)
app.factory('ServicoMultiplicacao', function() {
var servico = {};
servico.multiplicar = function(a, b) {
return a * b;
};
return servico;
});
// Service que usa a factory
app.service('ServicoCalculo', function(ServicoMultiplicacao) {
this.quadrado = function(valor) {
return ServicoMultiplicacao.multiplicar(valor, valor);
};
});
// Controller
app.controller('CalculadoraController', function($scope, ServicoCalculo, valorPadrao) {
$scope.numero = valorPadrao;
$scope.resultado = ServicoCalculo.quadrado($scope.numero);
$scope.calcularQuadrado = function() {
$scope.resultado = ServicoCalculo.quadrado($scope.numero);
};
});
</script>
</body>
</html>