Design Patterns com PHP – Injeção de dependência
O Design pattern chamado injeção de dependência aplica o conceito de inversão de controle, isso é muito importante de você entender logo de início.Calma!Calma!Só coloquei isso no começo desse artigo porque é uma coisa que tenho que dizer quando quero explicar o conceito de injeção de dependência, e isso é muito, muito mais simples do que parece.
Pense no seguinte cenário, você tem uma classe de Checkout
, e essa classe não sabe que tipo de gateway de pagamento vai usar, e para isso cria métodos para cada um deles, por exemplo:
class Checkout { public function pagseguro() { // implementacao aqui } public function paypal() { // implementacao aqui } public function pagarme() { // implementacao aqui } }
Já pensou ter que escrever a implementação de cada um desses gateways de pagamento em seus respectivos métodos?.Não seria errado(eu não gosto de apontar o dedo e falar que algo está definitivamente errado, é só uma maneira diferente de fazer), fazer isso, mas tem uma maneira muito mais amigável, que seria criar uma classe para cada tipo de pagamento e instanciar dentro de seus respectivos métodos na classe Checkout.
Ficando assim:
class Checkout { public function pagseguro() { $checkout = new Pagseguro(); } public function paypal() { $checkout = new PayPal(); } public function pagarme() { $checkout = new PagarMe(); } }
Bem melhor certo?.Com certeza!Mas ainda tem espaço para melhorar, nesse exemplo eu posso diminuir o número de métodos para somente 1, ao invés desses 3, vou criar somente o método chamado payment
, e vou passar por parâmetro(injetar a dependência) a instância que quero(o gateway escolhido).
E esse único método que criei tem um nome genérico(payment), assim pode ser usado por qualquer gateway de pagamento.
class Checkout { public function pay($checkout) { $checkout->pay(); } }
Agora no cliente(que é onde instancio essa classe Checkout) eu faço o seguinte.
$checkout = new Checkout; $checkout->payment(new Pagseguro);
Preste bem atenção agora, está vendo que dentro do método payment da classe Checkout estou chamando o método pay
da injeção de dependência(intância da classe passada por parâmetro no método payment do checkout)?
O que aconteceria se a classe Pagseguro não tivesse o método pay?.E se eu passasse a instância da classe PayPal e ela não tivesse o método pay?.Está entendendo onde quero chegar?.Sim, nas interfaces.
As interfaces são contratos, que a classe que implementa ela, assina, com isso ela(classe) concorda que tem que ter os métodos criados dentro do contrato(interface), por exemplo.
interface CheckoutInterface { public function payment(); } class Pagseguro implements CheckoutInterface { public function payment() { // implementação do pagamento do pagseguro } } class PayPal implements CheckoutInterface { public function payment() { // implementação do pagamento do paypal } }
Criando as classes de Pagamento implementando a interface CheckoutInterface
me dá a certeza que a classe tem esse método payment, exigido para fazer o checkout dentro do método pay
da classe Checkout
.
Agora não interessa qual classe de Pagamento eu passe para o Checkout, eu sei que vai ter o método payment, justamente por ela ter um contrato assinado(a interface CheckoutInterface) que tem esse método, com isso a classe tem que ter esse método também.
Mas onde que entra essa tal inversão de controle
?
Antes a instância da classe Pagseguro, PayPal e qualquer outro gateway, se dava dentro da classe, o controle de instanciar a classe de Pagamento estava dentro da classe Checkout, agora o controle foi invertido, essa instância se dá no cliente(onde instancio a classe Checkout) passando por parâmetro para o método pay(injeção de dependência).
Agora falta uma última coisa, no método pay da classe Checkout eu preciso ter a certeza que a instância que vou passar será de uma classe que tem um acordo com a interface CheckoutInterface
.
class Checkout { public function pay(CheckoutInterface $checkout) { $checkout->payment(); } } $checkout = new Checkout(); $checkout->payment(new Pagseguro()); // ou $checkout->payment(new PayPal());
Resumindo todo esse artigo: Injeção de dependência é um pattern onde passo a instância de uma classe para um método de outra classe, fazendo isso tiro o controle de criar a instância dentro dessa classe, passando agora essa responsabilidade para o cliente.
Pronto! Isso que é injeção de dependência e inversão de controle, simples demais, as vezes os nomes dão mais medo do que o código.
Se quiser conhecer meu trabalho mais a fundo, visite meu canal no YouTube e veja meus cursos completos clicando nos links abaixo.
🔥 Canal no YouTube: Ir para o canal no YouTube
🔥Veja meus cursos disponíveis: Ir para a lista de cursos
Magnífica explicação, parabéns!!!