Was ist Dependency Injection in C++ und warum wird es benötigt?
\n\nDependency Injection (DI) ist eines der Schlüsselprinzipien der objektorientierten Programmierung, das es ermöglicht, Code flexibler, testbarer und wartbarer zu machen. Wenn Sie neu in C++ sind und Begriffe wie "lose Kopplung" oder "Inversion of Control" gehört haben, aber nicht vollständig verstehen – dieser Artikel ist für Sie.
\n\nEinfach ausgedrückt ist Dependency Injection (Abhängigkeitsinjektion) eine Technik, bei der ein Objekt seine Abhängigkeiten von außen erhält, anstatt sie selbst zu erstellen. Anstatt dass eine Klasse selbst Objekte anderer Klassen erstellt, werden diese Objekte über den Konstruktor, Setter oder eine Schnittstelle in sie "injiziert".
\n\nProblem: Starke Kopplung (Tight Coupling)
\n\nStellen Sie sich vor, Sie schreiben eine Anwendung zum Senden von Benachrichtigungen. Ohne DI könnte Ihr Code so aussehen:
\n\n#include <iostream>\n#include <string>\n\nclass EmailService {\npublic:\n void send(const std::string& message) {\n std::cout << "E-Mail senden: " << message << std::endl;\n }\n};\n\nclass Notification {\nprivate:\n EmailService emailService; // Starke Abhängigkeit!\npublic:\n void notify(const std::string& msg) {\n emailService.send(msg);\n }\n};\n\nint main() {\n Notification notif;\n notif.notify("Hallo, Welt!");\n return 0;\n}\n\nIn diesem Beispiel ist die Klasse Notification stark an EmailService gebunden. Wenn Sie SMS-Benachrichtigungen oder Logging hinzufügen möchten, müssten Sie die Klasse Notification umschreiben. Solcher Code ist schwer zu testen, zu erweitern und zu warten.
Lösung: Abhängigkeitsinjektion (Dependency Injection)
\n\nUm das Problem der starken Kopplung zu lösen, verwenden wir DI. Die Grundidee besteht darin, eine Schnittstelle (abstrakte Klasse) für den Benachrichtigungsdienst zu definieren und diese von außen an die Klasse Notification zu übergeben.
Schritt 1: Erstellen einer abstrakten Schnittstelle
\n\n#include <iostream>\n#include <string>\n#include <memory>\n\n// Abstrakte Schnittstelle für alle Benachrichtigungsdienste\nclass IMessageService {\npublic:\n virtual ~IMessageService() = default;\n virtual void send(const std::string& message) = 0;\n};\n\nSchritt 2: Implementieren konkreter Dienste
\n\nclass EmailService : public IMessageService {\npublic:\n void send(const std::string& message) override {\n std::cout << "📧 E-Mail: " << 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\nSchritt 3: Abhängigkeit über den Konstruktor injizieren
\n\nclass Notification {\nprivate:\n std::unique_ptr<IMessageService> service; // Abhängigkeit wird von außen injiziert\npublic:\n // Injektion über den Konstruktor (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 // Konkrete Implementierung erstellen\n auto emailService = std::make_unique<EmailService>();\n \n // In Notification injizieren\n Notification notif(std::move(emailService));\n notif.notify("Dependency Injection funktioniert!");\n \n // Einfach auf SMS umstellen\n auto smsService = std::make_unique<SMSService>();\n Notification smsNotif(std::move(smsService));\n smsNotif.notify("Jetzt per SMS!");\n \n return 0;\n}\n\nDrei Hauptmethoden der Abhängigkeitsinjektion in C++
\n\n1. Constructor Injection (über den Konstruktor)
\nDie gebräuchlichste und empfohlene Methode. Abhängigkeiten werden bei der Erstellung des Objekts übergeben und bleiben während seiner gesamten Lebensdauer unverändert.
\n\n<