<aside> đ đ Category: Structural
</aside>
Bridge pattern memisahkan abstraction dari implementation-nya sehingga keduanya dapat berubah secara independen. Pattern ini menggunakan composition over inheritance untuk menghindari class explosion.
<aside> âšī¸ Analogi: Seperti remote control (abstraction) yang dapat bekerja dengan berbagai perangkat elektronik (implementations). Remote control dan perangkat dapat berkembang secara terpisah tanpa saling bergantung.
</aside>
Ketika Anda memiliki class hierarchy yang tumbuh dalam dua dimensi independen (misalnya: Shape à Color, atau Device à Remote), inheritance murni akan menyebabkan class explosion. Menambahkan varian baru memerlukan pembuatan banyak subclass baru.
Pisahkan hierarki menjadi dua bagian: abstraction (interface tingkat tinggi) dan implementation (platform-specific code). Abstraction memiliki reference ke implementation object dan mendelegasikan pekerjaan ke implementation tersebut.
// Implementation Interface
public interface IMessageSender
{
void SendMessage(string message);
}
// Concrete Implementations
public class EmailSender : IMessageSender
{
public void SendMessage(string message)
{
Console.WriteLine($"[EMAIL] Sending: {message}");
}
}
public class SmsSender : IMessageSender
{
public void SendMessage(string message)
{
Console.WriteLine($"[SMS] Sending: {message}");
}
}
public class SlackSender : IMessageSender
{
public void SendMessage(string message)
{
Console.WriteLine($"[SLACK] Sending: {message}");
}
}
// Abstraction
public abstract class Message
{
protected IMessageSender _sender;
protected Message(IMessageSender sender)
{
_sender = sender;
}
public abstract void Send();
}
// Refined Abstractions
public class TextMessage : Message
{
private string _content;
public TextMessage(IMessageSender sender, string content) : base(sender)
{
_content = content;
}
public override void Send()
{
_sender.SendMessage(_content);
}
}
public class UrgentMessage : Message
{
private string _content;
public UrgentMessage(IMessageSender sender, string content) : base(sender)
{
_content = content;
}
public override void Send()
{
_sender.SendMessage($"đ¨ URGENT: {_content}");
}
}
// Usage
var emailSender = new EmailSender();
var smsSender = new SmsSender();
var normalEmail = new TextMessage(emailSender, "Hello!");
normalEmail.Send(); // [EMAIL] Sending: Hello!
var urgentSms = new UrgentMessage(smsSender, "Server down!");
urgentSms.Send(); // [SMS] Sending: đ¨ URGENT: Server down!
from abc import ABC, abstractmethod
# Implementation Interface
class IMessageSender(ABC):
@abstractmethod
def send_message(self, message: str) -> None:
pass
# Concrete Implementations
class EmailSender(IMessageSender):
def send_message(self, message: str) -> None:
print(f"[EMAIL] Sending: {message}")
class SmsSender(IMessageSender):
def send_message(self, message: str) -> None:
print(f"[SMS] Sending: {message}")
class SlackSender(IMessageSender):
def send_message(self, message: str) -> None:
print(f"[SLACK] Sending: {message}")
# Abstraction
class Message(ABC):
def __init__(self, sender: IMessageSender):
self._sender = sender
@abstractmethod
def send(self) -> None:
pass
# Refined Abstractions
class TextMessage(Message):
def __init__(self, sender: IMessageSender, content: str):
super().__init__(sender)
self._content = content
def send(self) -> None:
self._sender.send_message(self._content)
class UrgentMessage(Message):
def __init__(self, sender: IMessageSender, content: str):
super().__init__(sender)
self._content = content
def send(self) -> None:
self._sender.send_message(f"đ¨ URGENT: {self._content}")
# Usage
email_sender = EmailSender()
sms_sender = SmsSender()
normal_email = TextMessage(email_sender, "Hello!")
normal_email.send() # [EMAIL] Sending: Hello!
urgent_sms = UrgentMessage(sms_sender, "Server down!")
urgent_sms.send() # [SMS] Sending: đ¨ URGENT: Server down!