🧩 Facade パターン
✅ 設計意図
- 複雑な内部構造や複数の処理を 1 つの簡潔なインターフェースにまとめる
- クライアントコードから詳細な手順や依存を隠蔽し、操作を簡単にする
- 使いやすく、安全な窓口(Facade)を用意して、呼び出し元のコードを疎結合に保つ
✅ 適用理由
- 古い API や複数の下位モジュールへの 直接アクセスが必要な処理を 1 つにまとめたい
- 呼び出し側のコードに 冗長な制御ロジック(初期化・整形・副処理など)が散らばってしまっている
- 変更に強く、保守しやすい構造にリファクタリングしたい
- UI やサービス層などから「内部の詳細を知らなくても使えるようにしたい」
✅ 向いているシーン
- 複雑な下位処理(API 呼び出し・設定・ログ・通知など)を 1 つのメソッドで完了させたい
- 古い API や複数の外部サービスを 統一インターフェースで使いたい
- テストやモック化のために 一括で抽象化したい
- 利用者(呼び出し側)を極力シンプルに保ちたいとき
- 一連の処理に失敗しにくい順序・制御が必要なとき(例:複数サービスの連携)
✅ コード例
- TypeScript
- PHP
- Python
// レガシーAPIや内部処理(複雑)
class LegacyPrinter {
printText(text: string) {
console.log(`*** ${text} ***`);
}
}
class FooterGenerator {
getFooter(): string {
return "---- END ----";
}
}
// Facade(簡潔なインターフェース)
class PrintFacade {
private printer = new LegacyPrinter();
private footerGen = new FooterGenerator();
printWithFooter(text: string) {
const formatted = text.toUpperCase();
this.printer.printText(formatted);
const footer = this.footerGen.getFooter();
this.printer.printText(footer);
}
}
// 呼び出し元
class ReportGenerator {
constructor(private facade: PrintFacade) {}
printSummary(text: string) {
this.facade.printWithFooter(text);
}
}
// 利用例
const printer = new PrintFacade();
const report = new ReportGenerator(printer);
report.printSummary("月次レポート");
<?php
class LegacyPrinter {
public function printText(string $text): void {
echo "*** {$text} ***\n";
}
}
class FooterGenerator {
public function getFooter(): string {
return "---- END ----";
}
}
class PrintFacade {
private LegacyPrinter $printer;
private FooterGenerator $footerGen;
public function __construct() {
$this->printer = new LegacyPrinter();
$this->footerGen = new FooterGenerator();
}
public function printWithFooter(string $text): void {
$formatted = strtoupper($text);
$this->printer->printText($formatted);
$footer = $this->footerGen->getFooter();
$this->printer->printText($footer);
}
}
class ReportGenerator {
public function __construct(private PrintFacade $facade) {}
public function printSummary(string $text): void {
$this->facade->printWithFooter($text);
}
}
// 利用例
$facade = new PrintFacade();
$report = new ReportGenerator($facade);
$report->printSummary("月次レポート");
class LegacyPrinter:
def print_text(self, text: str):
print(f"*** {text} ***")
class FooterGenerator:
def get_footer(self) -> str:
return "---- END ----"
class PrintFacade:
def __init__(self):
self.printer = LegacyPrinter()
self.footer_gen = FooterGenerator()
def print_with_footer(self, text: str):
formatted = text.upper()
self.printer.print_text(formatted)
footer = self.footer_gen.get_footer()
self.printer.print_text(footer)
class ReportGenerator:
def __init__(self, facade: PrintFacade):
self.facade = facade
def print_summary(self, text: str):
self.facade.print_with_footer(text)
# 利用例
facade = PrintFacade()
report = ReportGenerator(facade)
report.print_summary("月次レポート")
✅ 解説
このコードは Facade
パターン を使用して、複雑な内部処理(LegacyPrinter
や FooterGenerator
)を隠蔽し、
簡潔なインターフェース(PrintFacade
)を提供する設計を実現している。
Facade
パターンは、複雑なサブシステムを簡単に利用できるようにするための統一インターフェースを提供するデザインパターン。
1. Facade パターンの概要
- Subsystem Classes: 複雑な内部処理を提供するクラス
- このコードでは
LegacyPrinter
とFooterGenerator
が該当
- このコードでは
- Facade: サブシステムを統一的に利用するための簡潔なインターフェースを提供するクラス
- このコードでは
PrintFacade
が該当
- このコードでは
- Client:
Facade
を利用してサブシステムを操作するクラス- このコードでは
ReportGenerator
が該当
- このコードでは
2. 主なクラスとその役割
LegacyPrinter
- サブシステムの一部
- テキストを出力する旧仕様のクラス
FooterGenerator
- サブシステムの一部
- フッター文字列を生成するクラス
PrintFacade
Facade
クラスLegacyPrinter
とFooterGenerator
を統合し、簡潔なインターフェース(printWithFooter
)を提供
ReportGenerator
- クライアントクラス
PrintFacade
を利用して、レポートを出力
3. UML クラス図
4. Facade パターンの利点
- 簡潔なインターフェース: クライアントは複雑なサブシステムを意識せずに操作可能
- 疎結合: クライアントとサブシステム間の結合度を低減
- 保守性向上: サブシステムの変更が
Facade
内に閉じ込められるため、クライアントコードへの影響を最小化
この設計は、複雑な内部処理を隠蔽し、クライアントに対して簡潔なインターフェースを提供する必要がある場面で非常に有効であり、 コードの可読性と保守性を向上させる。