Dependency Inversion Principle
DIP
The Dependency Inversion Principle (DIP) is a design principle in object-oriented programming that states that high-level modules should not depend on low-level modules. Both should depend on abstractions. This principle aims to decouple modules, making the system more flexible, extensible, and easier to maintain.
It consists of two key points:
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
By following the DIP, changes in one module will not affect other modules, leading to a more modular and robust system.
// Define an abstract email sender trait
trait EmailSender {
fn send_email(&self, to: &str, subject: &str, body: &str);
}
// Implement the EmailSender trait for a text email sender
struct TextEmailSender;
impl EmailSender for TextEmailSender {
fn send_email(&self, to: &str, subject: &str, body: &str) {
println!("Sending text email to {} with subject '{}' and body: {}", to, subject, body);
}
}
// Implement the EmailSender trait for an HTML email sender
struct HTMLEmailSender;
impl EmailSender for HTMLEmailSender {
fn send_email(&self, to: &str, subject: &str, body: &str) {
println!("Sending HTML email to {} with subject '{}' and body: {}", to, subject, body);
}
}
// Function to send email notifications using any email sender that implements the EmailSender trait
fn send_notification<T: EmailSender>(email_sender: T, to: &str, subject: &str, body: &str) {
email_sender.send_email(to, subject, body);
}
fn main() {
// Use TextEmailSender to send a text email
let text_email_sender = TextEmailSender;
send_notification(text_email_sender, "example@example.com", "Test Subject", "This is a test email");
// Use HTMLEmailSender to send an HTML email
let html_email_sender = HTMLEmailSender;
send_notification(html_email_sender, "example@example.com", "Test Subject", "<h1>This is a test email</h1>");
}
In this example, we define an abstract trait EmailSender, which represents the abstraction of an email sender. Then, we implement this trait for two concrete types: TextEmailSender and HTMLEmailSender. The send_notification function demonstrates how we can use any type that implements the EmailSender trait to send email notifications without caring about the specific implementation details. This adheres to the Dependency Inversion Principle, as high-level modules (such as send_notification) depend on abstractions (EmailSender) rather than concrete implementations.