O que é Injeção de Dependência em C++ e para que serve?
\n\nInjeção de Dependência (DI) é um dos princípios-chave da programação orientada a objetos, que permite tornar o código mais flexível, testável e sustentável. Se você é iniciante em C++ e já ouviu termos como "baixo acoplamento" ou "inversão de controle", mas não os entende completamente — este artigo é para você.
\n\nEm palavras simples, Injeção de Dependência é uma técnica na qual um objeto recebe suas dependências externamente, em vez de criá-las por conta própria. Em vez de a classe criar objetos de outras classes, esses objetos são "injetados" nela através do construtor, setter ou interface.
\n\nProblema: alto acoplamento (tight coupling)
\n\nImagine que você está escrevendo um aplicativo para enviar notificações. Sem DI, seu código pode ficar assim:
\n\n#include <iostream>\n#include <string>\n\nclass EmailService {\npublic:\n void send(const std::string& message) {\n std::cout << "Enviando email: " << message << std::endl;\n }\n};\n\nclass Notification {\nprivate:\n EmailService emailService; // Dependência rígida!\npublic:\n void notify(const std::string& msg) {\n emailService.send(msg);\n }\n};\n\nint main() {\n Notification notif;\n notif.notify("Hello, World!");\n return 0;\n}\n\nNeste exemplo, a classe Notification está rigidamente acoplada a EmailService. Se você quiser adicionar notificações SMS ou logging — terá que reescrever a classe Notification. Esse código é difícil de testar, estender e manter.
Solução: Injeção de Dependência
\n\nPara resolver o problema do alto acoplamento, usamos DI. A ideia principal é criar uma interface (classe abstrata) para o serviço de notificações e passá-la para a classe Notification externamente.
Passo 1: Criamos uma interface abstrata
\n\n#include <iostream>\n#include <string>\n#include <memory>\n\n// Interface abstrata para todos os serviços de notificação\nclass IMessageService {\npublic:\n virtual ~IMessageService() = default;\n virtual void send(const std::string& message) = 0;\n};\n\nPasso 2: Implementamos serviços concretos
\n\nclass EmailService : public IMessageService {\npublic:\n void send(const std::string& message) override {\n std::cout << "📧 Email: " << message << std::endl;\n }\n};\n\nclass SMSService : public IMessageService {\npublic:\n void send(const std::string& message) override {\n std::cout << "📱 SMS: " << message << std::endl;\n }\n};\n\nPasso 3: Injetamos a dependência através do construtor
\n\nclass Notification {\nprivate:\n std::unique_ptr<IMessageService> service; // Dependência injetada externamente\npublic:\n // Injeção via construtor (Constructor Injection)\n Notification(std::unique_ptr<IMessageService> svc) \n : service(std::move(svc)) {}\n \n void notify(const std::string& msg) {\n service->send(msg);\n }\n};\n\nint main() {\n // Criamos uma implementação concreta\n auto emailService = std::make_unique<EmailService>();\n \n // Injetamos ela em Notification\n Notification notif(std::move(emailService));\n notif.notify("Injeção de Dependência funciona!");\n \n // Trocamos facilmente para SMS\n auto smsService = std::make_unique<SMSService>();\n Notification smsNotif(std::move(smsService));\n smsNotif.notify("Agora via SMS!");\n \n return 0;\n}\n\nTrês formas principais de injeção de dependências em C++
\n\n1. Constructor Injection (via construtor)
\nA forma mais comum e recomendada. As dependências são passadas na criação do objeto e permanecem inalteradas durante sua vida útil.
\n\n<