メインコンテンツまでスキップ

🧩 Decorator パターン

✅ 設計意図

  • 処理に追加の振る舞いをラップして重ねる構造
  • 継承ではなく「合成」で振る舞いを追加できる

✅ 適用理由

  • 元の export 処理を変えずにログ機能を追加
  • 追加機能を柔軟に組み合わせ可能

✅ 向いているシーン

  • ログ・バリデーション・権限チェックなど、横断的な処理を再利用したい

✅ コード例

// コンポーネントインターフェース
interface Exporter {
export(data: string): void;
}

// 具象コンポーネント
class PdfExporter implements Exporter {
export(data: string): void {
console.log(`PDF出力: ${data}`);
}
}

class CsvExporter implements Exporter {
export(data: string): void {
console.log(`CSV出力: ${data}`);
}
}

// デコレータ(共通機能)
class LoggingExporter implements Exporter {
constructor(private wrapped: Exporter) {}

export(data: string): void {
console.log("開始ログ");
this.wrapped.export(data);
console.log("完了ログ");
}
}

// 利用例
const pdf = new LoggingExporter(new PdfExporter());
pdf.export("帳票データ");

const csv = new LoggingExporter(new CsvExporter());
csv.export("ユーザー一覧");

✅ 解説

このコードは Decorator パターン を使用して、既存の機能(データ出力)に追加の機能(ログ出力)を動的に付加する設計を実現している。 Decorator パターンは、オブジェクトに動的に責務を追加する柔軟な方法を提供するデザインパターンであり、継承を使わずに機能を拡張できる。

1. Decorator パターンの概要

  • Component: 基本機能を定義する共通インターフェース
    • このコードでは Exporter が該当
  • ConcreteComponent: Component を実装し、基本機能を提供するクラス
    • このコードでは PdfExporterCsvExporter が該当
  • Decorator: Component を実装し、基本機能に追加の機能を付加するクラス
    • このコードでは LoggingExporter が該当
  • ConcreteDecorator: Decorator を拡張して、具体的な追加機能を提供するクラス
    • このコードでは LoggingExporter がその役割を担う

2. 主なクラスとその役割

  • Exporter
    • 基本機能を定義するインターフェース
    • export(data: string): void メソッドを定義
  • PdfExporter, CsvExporter
    • Exporter を実装した具体的なコンポーネント
    • PDF または CSV 形式でデータを出力
  • LoggingExporter
    • Decorator クラス
    • Exporter をラップし、データ出力の前後にログ出力を追加

3. UML クラス図

4. Decorator パターンの利点

  • 動的な機能追加: 継承を使わずに、既存のオブジェクトに動的に機能を追加可能
  • 柔軟性: 複数のデコレータを組み合わせて機能を拡張可能
  • オープン/クローズド原則: 既存のクラスを変更せずに機能を拡張可能

この設計は、既存の機能に追加の責務を柔軟に付加する必要がある場面で非常に有効であり、コードの再利用性と拡張性を向上させる。