🧩 Facade パターン
✅ 設計意図
- 複雑な内部処理を隠蔽し、外部にはシンプルなインターフェースを提供
- ユーザーに対して「使いやすい窓口」となる
✅ 適用理由
- ユースケース(注文処理)を外から 1 つのインターフェースで呼び出せる
- 各機能の責務は分離されたまま統合
✅ 向いているシーン
- ビジネスロジックをモジュール化した上でまとめたい
- 「〇〇処理一式」を 1 関数でまとめたい
✅ コード例
- TypeScript
- PHP
- Python
// 個別責務のクラスたち
class DiscountCalculator {
static calculate(base: number, type: string): number {
switch (type) {
case "student":
return base * 0.8;
case "member":
return base * 0.9;
default:
return base;
}
}
}
class InventoryService {
static reduce(productIds: string[]) {
console.log(`在庫を ${productIds.length} 件分減らしました`);
}
}
class EmailService {
static send(email: string, message: string) {
console.log(`メールを ${email} に送信: ${message}`);
}
}
class OrderLogger {
static log(orderId: string) {
console.log(`注文ログを記録: ${orderId}`);
}
}
// Facadeクラス
class OrderProcessor {
constructor(
private productIds: string[],
private userEmail: string,
private discountType: string
) {}
confirmOrder() {
const basePrice = this.productIds.length * 1000;
const total = DiscountCalculator.calculate(basePrice, this.discountType);
InventoryService.reduce(this.productIds);
EmailService.send(
this.userEmail,
`ご注文が確定しました(合計: ¥${total})`
);
OrderLogger.log("order-" + Math.random().toString(36).substring(2));
}
}
// 利用例
const facadeProcessor = new OrderProcessor(
["p01", "p02"],
"hiroshi@example.com",
"student"
);
facadeProcessor.confirmOrder();
<?php
// 個別責務のクラスたち
class DiscountCalculator {
public static function calculate(float $base, string $type): float {
switch ($type) {
case "student":
return $base * 0.8;
case "member":
return $base * 0.9;
default:
return $base;
}
}
}
class InventoryService {
public static function reduce(array $productIds): void {
echo "在庫を " . count($productIds) . " 件分減らしました\\n";
}
}
class EmailService {
public static function send(string $email, string $message): void {
echo "メールを {$email} に送信: {$message}\\n";
}
}
class OrderLogger {
public static function log(string $orderId): void {
echo "注文ログを記録: {$orderId}\\n";
}
}
// Facadeクラス
class OrderProcessor {
public function __construct(
private array $productIds,
private string $userEmail,
private string $discountType
) {}
public function confirmOrder(): void {
$basePrice = count($this->productIds) * 1000;
$total = DiscountCalculator::calculate($basePrice, $this->discountType);
InventoryService::reduce($this->productIds);
EmailService::send($this->userEmail, "ご注文が確定しました(合計: ¥{$total})");
$orderId = "order-" . substr(md5((string)mt_rand()), 0, 8);
OrderLogger::log($orderId);
}
}
// 利用例
$processor = new OrderProcessor(
["p01", "p02"],
"hiroshi@example.com",
"student"
);
$processor->confirmOrder();
import random
import string
# 個別責務のクラスたち
class DiscountCalculator:
@staticmethod
def calculate(base: float, discount_type: str) -> float:
if discount_type == "student":
return base * 0.8
elif discount_type == "member":
return base * 0.9
return base
class InventoryService:
@staticmethod
def reduce(product_ids: list[str]):
print(f"在庫を {len(product_ids)} 件分減らしました")
class EmailService:
@staticmethod
def send(email: str, message: str):
print(f"メールを {email} に送信: {message}")
class OrderLogger:
@staticmethod
def log(order_id: str):
print(f"注文ログを記録: {order_id}")
# Facadeクラス
class OrderProcessor:
def __init__(self, product_ids: list[str], user_email: str, discount_type: str):
self.product_ids = product_ids
self.user_email = user_email
self.discount_type = discount_type
def confirm_order(self):
base_price = len(self.product_ids) * 1000
total = DiscountCalculator.calculate(base_price, self.discount_type)
InventoryService.reduce(self.product_ids)
EmailService.send(self.user_email, f"ご注文が確定しました(合計: ¥{total})")
order_id = "order-" + ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
OrderLogger.log(order_id)
# 利用例
processor = OrderProcessor(
["p01", "p02"],
"hiroshi@example.com",
"student"
)
processor.confirm_order()
✅ 解説
このコードは Facade
パターン を使用して、注文処理の複雑な内部ロジックを隠蔽し、外部からはシンプルなインターフェース (OrderProcessor
) を提供している。
Facade
パターンは、複雑なサブシステムを簡単に利用できるようにするための「窓口」を提供するデザインパターン。
1. Facade パターンの概要
- このコードでは、
OrderProcessor
クラスがFacade
として機能し、以下の複数の責務を持つクラスを統合している:DiscountCalculator
: 割引計算を担当InventoryService
: 在庫管理を担当EmailService
: メール送信を担当OrderLogger
: 注文ログの記録を担当
2. 主なクラスとその役割
DiscountCalculator
- 割引計算を行うユーティリティクラス
- 割引タイプ(
student
,member
,default
)に応じて価格を計算する
InventoryService
- 在庫を減らす処理を担当するクラス
EmailService
- 指定されたメールアドレスにメッセージを送信するクラス
OrderLogger
- 注文ログを記録するクラス
OrderProcessor
Facade
クラス- 上記の複数のクラスを統合し、注文処理を簡潔に実行するインターフェースを提供する
confirmOrder
メソッドで以下の処理を行う:- 基本価格を計算
- 割引後の合計金額を計算
- 在庫を減らす
- メールを送信
- 注文ログを記録
3. UML クラス図
4. Facade パターンの利点
- 簡潔なインターフェース: 外部からは
OrderProcessor
を使うだけで注文処理が完結する - 責務の分離: 各クラスが単一の責務を持つため、コードの保守性が向上する
- 再利用性: サブシステム(
DiscountCalculator
など)は独立しているため、他のシステムでも再利用可能
この設計は、複雑な処理を隠蔽しつつ、各クラスの責務を明確に分離している。