#include <iostream>
using namespace std;
#include <iostream>
// Tightly coupled to specific implementations
class Notification {
public:
void sendEmail(const std::string& message) {
std::cout << "Sending Email: " << message << "\n";
}
void sendSMS(const std::string& message) {
std::cout << "Sending SMS: " << message << "\n";
}
};
//It is not follwing dependency inversion principles because
//The Notification class is directly tied to the sendEmail and sendSMS methods.
//Adding a new notification method (e.g., PushNotification) would require modifying the Notification class.
//Lets make this follow DIP
// Abstract base class (Abstraction)
class Notifier {
public:
virtual void sendNotification(const std::string& message) const = 0;
virtual ~Notifier() = default;
};
// Concrete implementation: Email Notifier
class EmailNotifier : public Notifier {
public:
void sendNotification(const std::string& message) const override {
std::cout << "Sending Email: " << message << "\n";
}
};
// Concrete implementation: SMS Notifier
class SMSNotifier : public Notifier {
public:
void sendNotification(const std::string& message) const override {
std::cout << "Sending SMS: " << message << "\n";
}
};
// High-level module depends on abstraction (Notifier)
class Notification {
private:
Notifier& notifier; // Dependency is injected via reference
public:
Notification(Notifier& n) : notifier(n) {}
void alert(const std::string& message) {
notifier.sendNotification(message);
}
};