🧩 Proxy パターン
✅ 設計意図
- 本物のオブジェクト(Real Subject)へのアクセスを間接化し、その前段に制御・検査・遅延処理などの役割を持たせる
- 呼び出し元は Proxy 経由でアクセスするため、本体を意識せずに操作できる構造を作る
- アクセス制限・キャッシュ・ログ・ネットワーク経由の操作などを透明に挟み込む
✅ 適用理由
- 重い処理(例:リモートサービス、画像ロード、大量データ)に対して、必要になるまで本体を生成したくない(遅延評価)
- アクセス制御や前処理(認証、ログ、チェック)を共通化したい
- 実際の処理を変更せず、代理層を挟んで拡張したい
- 本体に影響を与えずに制御ロジックを追加したい(OCP に沿った変更)
✅ 向いているシーン
- 大きなオブジェクトを後で初期化したい(遅延ロード)
- 実際の処理にアクセス制限や前後処理を追加したい
- 通信の境界(例:RPC, REST API)を抽象化して隠したい
- キャッシュやログ、モニタリングを間に挟みたい
- テストやモックの場面で 本体の代替を提供したい
✅ コード例
- TypeScript
- PHP
- Python
// インターフェース
interface Printer {
print(text: string): void;
}
// 実際の処理を行うクラス(本体)
class RealPrinter implements Printer {
print(text: string): void {
console.log(`印刷中: ${text}`);
}
}
// Proxy(アクセスを仲介)
class PrinterProxy implements Printer {
private real: RealPrinter;
constructor() {
this.real = new RealPrinter();
}
print(text: string): void {
console.log("ログ: 印刷を開始します");
this.real.print(text);
console.log("ログ: 印刷が完了しました");
}
}
// 利用例
const printer: Printer = new PrinterProxy();
printer.print("月次レポート");
<?php
interface Printer {
public function print(string $text): void;
}
class RealPrinter implements Printer {
public function print(string $text): void {
echo "印刷中: {$text}\n";
}
}
class PrinterProxy implements Printer {
private RealPrinter $real;
public function __construct() {
$this->real = new RealPrinter();
}
public function print(string $text): void {
echo "ログ: 印刷を開始します\n";
$this->real->print($text);
echo "ログ: 印刷が完了しました\n";
}
}
// 利用例
$printer = new PrinterProxy();
$printer->print("月次レポート");
from abc import ABC, abstractmethod
class Printer(ABC):
@abstractmethod
def print(self, text: str):
pass
class RealPrinter(Printer):
def print(self, text: str):
print(f"印刷中: {text}")
class PrinterProxy(Printer):
def __init__(self):
self._real = RealPrinter()
def print(self, text: str):
print("ログ: 印刷を開始します")
self._real.print(text)
print("ログ: 印刷が完了しました")
# 利用例
printer = PrinterProxy()
printer.print("月次レポート")
✅ 解説
このコードは Proxy
パターン を使用して、RealPrinter
へのアクセスを PrinterProxy
が仲介する設計を実現している。
Proxy
パターンは、オブジェクトへのアクセスを制御するための代理を提供するデザインパターンであり、
アクセス制御、ログ記録、遅延初期化などに利用される。
1. Proxy パターンの概要
- Subject: クライアントが利用する共通インターフェース
- このコードでは
Printer
が該当
- このコードでは
- RealSubject: 実際の処理を行うクラス
- このコードでは
RealPrinter
が該当
- このコードでは
- Proxy:
RealSubject
へのアクセスを制御するクラス- このコードでは
PrinterProxy
が該当
- このコードでは
- Client:
Subject
を通じてRealSubject
またはProxy
を利用するクラス- このコードでは
printer.print("月次レポート")
を呼び出す部分が該当
- このコードでは
2. 主なクラスとその役割
Printer
- 共通インターフェース(
Subject
) print(text: string): void
メソッドを定義
- 共通インターフェース(
RealPrinter
- 実際の処理を行うクラス(
RealSubject
) print
メソッドでテキストを印刷
- 実際の処理を行うクラス(
PrinterProxy
- Proxy クラス
RealPrinter
をラップし、アクセスを制御- 印刷処理の前後にログを出力
- クライアントコード
PrinterProxy
を通じてRealPrinter
を利用
3. UML クラス図
4. Proxy パターンの利点
- アクセス制御: クライアントが直接
RealPrinter
にアクセスするのを防ぎ、アクセス制御を実現 - 追加機能の付加: 実際の処理の前後にログ出力やキャッシュ処理などを追加可能
- 遅延初期化: 必要になるまで
RealPrinter
を生成しないようにすることも可能
この設計は、オブジェクトへのアクセスを制御したり、処理の前後に追加の機能を付加する必要がある場面で非常に有効であり、 コードの柔軟性と保守性を向上させる。