The Bridge Design Pattern is a structural pattern that separates abstraction from implementation so that the two can vary independently. It involves creating a bridge interface that decouples an abstraction from its implementation. This pattern is useful when you want to avoid a permanent binding between an abstraction and its implementation.
Let's illustrate the Bridge Pattern with a Ruby on Rails example. In this example, we'll create a bridge between different notification types and the way they are sent.
Abstraction: Notification
# Abstraction: Notification
class Notification
def initialize(sender)
@sender = sender
end
def send_message
raise NotImplementedError, 'Subclasses must implement the send_message method'
end
end
Refined Abstraction: EmailNotification, SMSNotification
# Refined Abstraction: EmailNotification
class EmailNotification < Notification
def send_message
@sender.send_message('Sending email notification.')
end
end
# Refined Abstraction: SMSNotification
class SMSNotification < Notification
def send_message
@sender.send_message('Sending SMS notification.')
end
end
Implementor: MessageSender
# Implementor: MessageSender
class MessageSender
def send_message(message)
raise NotImplementedError, 'Subclasses must implement the send_message method'
end
end
Concrete Implementor: EmailSender, SMSSender
# Concrete Implementor: EmailSender
class EmailSender < MessageSender
def send_message(message)
puts "EmailSender: #{message}"
end
end
# Concrete Implementor: SMSSender
class SMSSender < MessageSender
def send_message(message)
puts "SMSSender: #{message}"
end
end
Client Code: Using the Bridge
# Client code using the Bridge Pattern
email_sender = EmailSender.new
sms_sender = SMSSender.new
email_notification = EmailNotification.new(email_sender)
sms_notification = SMSNotification.new(sms_sender)
email_notification.send_message
sms_notification.send_message
In this example:
-
Notification
is the abstraction, representing different types of notifications. -
EmailNotification
andSMSNotification
are refined abstractions, representing specific types of notifications. -
MessageSender
is the implementor interface, defining the method for sending messages. -
EmailSender
andSMSSender
are concrete implementors, providing specific implementations for sending email and SMS messages. - The client code uses the Bridge Pattern to associate different types of notifications with different message senders, allowing the two to vary independently.
The Bridge Pattern is useful when you want to avoid a permanent binding between an abstraction and its implementation. It allows you to extend both hierarchies independently and change their implementations dynamically at runtime.