🧩 Proxy × Strategy
✅ 組み合わせの意図
Proxy
パターンで通知の アクセス制御やログ出力 をラップし、- 実際の送信処理は
Strategy
パターンで切り替え可能な通知手段として分離
この設計により、通知の振る舞い(送信手段)を戦略として柔軟に差し替えつつ、外側では Proxy によって共通の制御(ログ、認証、検閲など)を適用できる。
✅ よく使われるシーン
- 通知処理の共通フロー(ログやトレース)を Proxy でラップしつつ、通知内容は戦略的に差し替えたいとき
- 開発環境ではモック通知、本番ではメールや Slack などの通知方式を切り替えたいとき
- 外部 API の実行制御(頻度制限・認可など) を Proxy に集約し、送信方式は柔軟に変更したい場合
✅ UML クラス図
✅ コード例
- TypeScript
- PHP
- Python
interface NotificationStrategy {
send(user: string, message: string): void;
}
class EmailStrategy implements NotificationStrategy {
send(user: string, message: string): void {
console.log(`[Email] To: ${user}, Message: ${message}`);
}
}
class SlackStrategy implements NotificationStrategy {
send(user: string, message: string): void {
console.log(`[Slack] To: ${user}, Message: ${message}`);
}
}
interface Notifier {
notify(user: string, message: string): void;
}
class RealNotifier implements Notifier {
constructor(private strategy: NotificationStrategy) {}
notify(user: string, message: string): void {
this.strategy.send(user, message);
}
}
class NotifierProxy implements Notifier {
constructor(private real: Notifier) {}
notify(user: string, message: string): void {
if (!user.includes("@")) {
console.log("Invalid user. Notification aborted.");
return;
}
console.log("Proxy: Access check passed.");
this.real.notify(user, message);
console.log("Proxy: Notification sent.");
}
}
// Usage
const realNotifier = new RealNotifier(new EmailStrategy());
const proxy = new NotifierProxy(realNotifier);
proxy.notify("taro@example.com", "Disk space warning");
<?php
interface NotificationStrategy {
public function send(string $user, string $message): void;
}
class EmailStrategy implements NotificationStrategy {
public function send(string $user, string $message): void {
echo "[Email] To: {$user}, Message: {$message}\n";
}
}
class SlackStrategy implements NotificationStrategy {
public function send(string $user, string $message): void {
echo "[Slack] To: {$user}, Message: {$message}\n";
}
}
interface Notifier {
public function notify(string $user, string $message): void;
}
class RealNotifier implements Notifier {
private NotificationStrategy $strategy;
public function __construct(NotificationStrategy $strategy) {
$this->strategy = $strategy;
}
public function notify(string $user, string $message): void {
$this->strategy->send($user, $message);
}
}
class NotifierProxy implements Notifier {
private Notifier $real;
public function __construct(Notifier $real) {
$this->real = $real;
}
public function notify(string $user, string $message): void {
if (strpos($user, "@") === false) {
echo "Invalid user. Notification aborted.\n";
return;
}
echo "Proxy: Access check passed.\n";
$this->real->notify($user, $message);
echo "Proxy: Notification sent.\n";
}
}
// Usage
$realNotifier = new RealNotifier(new EmailStrategy());
$proxy = new NotifierProxy($realNotifier);
$proxy->notify("taro@example.com", "Disk space warning");
from abc import ABC, abstractmethod
class NotificationStrategy(ABC):
@abstractmethod
def send(self, user: str, message: str) -> None:
pass
class EmailStrategy(NotificationStrategy):
def send(self, user: str, message: str) -> None:
print(f"[Email] To: {user}, Message: {message}")
class SlackStrategy(NotificationStrategy):
def send(self, user: str, message: str) -> None:
print(f"[Slack] To: {user}, Message: {message}")
class Notifier(ABC):
@abstractmethod
def notify(self, user: str, message: str) -> None:
pass
class RealNotifier(Notifier):
def __init__(self, strategy: NotificationStrategy):
self.strategy = strategy
def notify(self, user: str, message: str) -> None:
self.strategy.send(user, message)
class NotifierProxy(Notifier):
def __init__(self, real: Notifier):
self.real = real
def notify(self, user: str, message: str) -> None:
if "@" not in user:
print("Invalid user. Notification aborted.")
return
print("Proxy: Access check passed.")
self.real.notify(user, message)
print("Proxy: Notification sent.")
# Usage
real_notifier = RealNotifier(EmailStrategy())
proxy = NotifierProxy(real_notifier)
proxy.notify("taro@example.com", "Disk space warning")
✅ 解説
NotificationStrategy
は通知戦略の共通インターフェースEmailStrategy
,SlackStrategy
は通知手段の具象戦略RealNotifier
は実際の送信処理を担当し、Strategy
を注入されるNotifierProxy
は通知の前後にログや制御処理を追加し、RealNotifier
に処理を委譲(Proxy
)
このように、可変ロジック(戦略)と共通制御(Proxy)を分離することで、単一責任を維持しながら柔軟で保守性の高い通知処理が実現できる。
✅ まとめ
- Proxy により、共通制御(ログ・認証・監査など)を一元化
- Strategy により、通知手段(メール・Slack・モックなど)を柔軟に切り替え
- 共通制御と振る舞いの切り替えを分離し、拡張性・テスト性・再利用性が高い設計