🧩 Bridge Pattern
✅ Intent
- Decouple abstraction from implementation so they can vary independently
- Enables the composition of independent dimensions (e.g., notification type × delivery method)
✅ Motivation
- You want to vary what is being done (e.g., normal vs urgent notification) separately from how it’s done (e.g., Email vs Slack)
- Avoid class explosion like
UrgentEmailNotification
,NormalEmailNotification
,UrgentSlackNotification
, etc.
✅ When to Use
- When you have two or more independent dimensions of variability
- When you want to extend abstraction and implementation hierarchies separately
✅ Code Example
- TypeScript
- PHP
- Python
// 実装クラス(通知手段)
interface Notifier {
sendMessage(to: string, content: string): void;
}
class EmailNotifier implements Notifier {
sendMessage(to: string, content: string): void {
console.log("件名: お知らせ");
console.log(`本文: ${content}`);
console.log(`宛先: ${to}@example.com`);
}
}
class SlackNotifier implements Notifier {
sendMessage(to: string, content: string): void {
console.log(`Slack宛: ${to}`);
console.log(`内容: ${content}`);
}
}
// 抽象クラス(通知処理)
abstract class Notification {
constructor(protected notifier: Notifier) {}
abstract notify(user: string, message: string): void;
}
// 拡張された抽象クラス
class NormalNotification extends Notification {
notify(user: string, message: string): void {
this.notifier.sendMessage(user, message);
}
}
class UrgentNotification extends Notification {
notify(user: string, message: string): void {
this.notifier.sendMessage(user, `[緊急] ${message}`);
}
}
// 利用例
const emailUrgent = new UrgentNotification(new EmailNotifier());
emailUrgent.notify("hiroshi", "サーバーが落ちました");
const slackNormal = new NormalNotification(new SlackNotifier());
slackNormal.notify("hiroshi", "定例ミーティングは15時です");
<?php
interface Notifier {
public function sendMessage(string $to, string $content): void;
}
class EmailNotifier implements Notifier {
public function sendMessage(string $to, string $content): void {
echo "件名: お知らせ\n";
echo "本文: {$content}\n";
echo "宛先: {$to}@example.com\n";
}
}
class SlackNotifier implements Notifier {
public function sendMessage(string $to, string $content): void {
echo "Slack宛: {$to}\n";
echo "内容: {$content}\n";
}
}
abstract class Notification {
public function __construct(protected Notifier $notifier) {}
abstract public function notify(string $user, string $message): void;
}
class NormalNotification extends Notification {
public function notify(string $user, string $message): void {
$this->notifier->sendMessage($user, $message);
}
}
class UrgentNotification extends Notification {
public function notify(string $user, string $message): void {
$this->notifier->sendMessage($user, "[緊急] {$message}");
}
}
// 利用例
$notification1 = new UrgentNotification(new EmailNotifier());
$notification1->notify("hiroshi", "サーバーが落ちました");
$notification2 = new NormalNotification(new SlackNotifier());
$notification2->notify("hiroshi", "定例ミーティングは15時です");
from abc import ABC, abstractmethod
# 実装側(Bridge の下部)
class Notifier(ABC):
@abstractmethod
def send_message(self, to: str, content: str):
pass
class EmailNotifier(Notifier):
def send_message(self, to: str, content: str):
print("件名: お知らせ")
print(f"本文: {content}")
print(f"宛先: {to}@example.com")
class SlackNotifier(Notifier):
def send_message(self, to: str, content: str):
print(f"Slack宛: {to}")
print(f"内容: {content}")
# 抽象側(Bridge の上部)
class Notification(ABC):
def __init__(self, notifier: Notifier):
self.notifier = notifier
@abstractmethod
def notify(self, user: str, message: str):
pass
class NormalNotification(Notification):
def notify(self, user: str, message: str):
self.notifier.send_message(user, message)
class UrgentNotification(Notification):
def notify(self, user: str, message: str):
self.notifier.send_message(user, f"[緊急] {message}")
# 利用例
email_urgent = UrgentNotification(EmailNotifier())
email_urgent.notify("hiroshi", "サーバーが落ちました")
slack_normal = NormalNotification(SlackNotifier())
slack_normal.notify("hiroshi", "定例ミーティングは15時です")
✅ Explanation
This code uses the Bridge
pattern to separate how notifications are sent (Notifier
) from how they're formatted or triggered (Notification
).
This allows you to mix and match behavior without creating deeply nested inheritance hierarchies.
1. Bridge Pattern Overview
-
Abstraction: Defines the abstract logic and holds a reference to the implementation
→Notification
-
RefinedAbstraction: Subclasses of the abstraction with specific behavior
→NormalNotification
,UrgentNotification
-
Implementor: Interface for platform-specific logic
→Notifier
-
ConcreteImplementor: Concrete implementations of delivery mechanisms
→EmailNotifier
,SlackNotifier
2. Key Classes and Responsibilities
-
Notifier
- Defines how to send messages (
sendMessage(to, content)
)
- Defines how to send messages (
-
EmailNotifier
,SlackNotifier
- Send messages through different platforms
-
Notification
- Defines the notification logic and delegates sending to
Notifier
- Defines the notification logic and delegates sending to
-
NormalNotification
,UrgentNotification
- Customize message formats or urgency levels
3. UML Class Diagram
4. Benefits of the Bridge Pattern
- Independent evolution: Add new delivery mechanisms or notification formats independently
- Avoid class explosion: No need for one class per combination
- Improved flexibility: Behavior can be composed at runtime
This design is particularly useful when you're dealing with multiple variations that shouldn't be hardcoded. The bridge enables modular design and better separation of concerns.