💡

デザインパターンを学ぶ #5 Decorator(デコレーター)

に公開

1. はじめに

デザインパターン学習シリーズの第5回。今回は「Decorator(デコレーター)」パターンを取り上げます。
目的は「既存のクラスを変更せずに、機能を後付けで追加する方法」を理解することです。

2. Decorator とは?

Decorator パターンは「元のオブジェクトをラップして、処理を委譲しつつ追加機能を差し込む」仕組みです。
継承を使わずに柔軟な拡張ができ、必要な分だけ積み重ねることができます。

例えば通知処理において「基本の通知」に加えて「Slack へも通知」「Email へも通知」を足したいとき、Decorator を使えば if 文を増やさず拡張できます。

3. 実装例(PHP)

interface Notifier {
    public function send(string $message): void;
}

class BasicNotifier implements Notifier {
    public function send(string $message): void {
        echo "Send: {$message}\n";
    }
}

abstract class NotifierDecorator implements Notifier {
    protected Notifier $wrappee;
    public function __construct(Notifier $notifier) {
        $this->wrappee = $notifier;
    }
}

class SlackNotifier extends NotifierDecorator {
    public function send(string $message): void {
        $this->wrappee->send($message);
        echo "Also send to Slack: {$message}\n";
    }
}

class EmailNotifier extends NotifierDecorator {
    public function send(string $message): void {
        $this->wrappee->send($message);
        echo "Also send Email: {$message}\n";
    }
}

// 利用例
$notifier = new EmailNotifier(
    new SlackNotifier(
        new BasicNotifier()
    )
);
$notifier->send("System down!");

出力例

Send: System down!
Also send to Slack: System down!
Also send Email: System down!

4. メリットと注意点

メリット

  • 既存コードを変更せず拡張できる
  • 必要な機能を積み重ねて組み合わせられる
  • 実行時に差し替えが可能で柔軟

注意点

  • デコレーターが増えるとクラス数が膨らむ
  • ラップの順番依存が発生する可能性がある

5. 実務での利用例

  • 通知処理(基本 → Slack → Email → Push通知を積み重ね)
  • ログ記録やメトリクス収集の追加
  • キャッシュやリトライの横断的な処理を足す

6. まとめ

Decorator パターンは「既存の処理をラップし、前後に機能を追加する」仕組みです。
継承せずに拡張できるため、横断的な処理を積み木のように組み合わせたいときに役立ちます。

Discussion