Proxy パターン
オブジェクトへのアクセスを代理オブジェクトが仲介し、アクセス制御やキャッシュなどの付加機能を提供するパターン
設計パターン基礎
Proxy パターンとは
Proxy パターンは、本物のオブジェクト (Real Subject) の前に代理オブジェクト (Proxy) を配置し、アクセス制御、遅延初期化、キャッシュ、ログ記録などの付加機能を透過的に提供する GoF デザインパターンである。クライアントは Proxy と Real Subject を区別せずに使える。
Proxy の種類
| 種類 | 目的 | 例 |
|---|---|---|
| キャッシュプロキシ | 結果をキャッシュして高速化 | API レスポンスのキャッシュ |
| 保護プロキシ | アクセス権限をチェック | 認証・認可の検証 |
| 仮想プロキシ | 重いオブジェクトの遅延初期化 | 画像の遅延読み込み |
| ログプロキシ | アクセスを記録 | API 呼び出しのログ |
| リモートプロキシ | リモートオブジェクトをローカルに見せる | gRPC クライアント |
TypeScript での実装
interface UserRepository {
findById(id: string): Promise<User | null>;
}
// Real Subject
class DynamoDBUserRepo implements UserRepository {
async findById(id: string) {
return ddb.send(new GetCommand({ TableName: 'Users', Key: { id } }));
}
}
// キャッシュプロキシ
class CachedUserRepo implements UserRepository {
private cache = new Map<string, { user: User | null; expiry: number }>();
constructor(private real: UserRepository, private ttlMs = 60000) {}
async findById(id: string) {
const cached = this.cache.get(id);
if (cached && Date.now() < cached.expiry) return cached.user;
const user = await this.real.findById(id);
this.cache.set(id, { user, expiry: Date.now() + this.ttlMs });
return user;
}
}
// 使用: クライアントは Proxy と Real Subject を区別しない
const repo: UserRepository = new CachedUserRepo(new DynamoDBUserRepo());
JavaScript の Proxy オブジェクト
JavaScript には言語レベルの Proxy オブジェクトがあり、プロパティアクセスやメソッド呼び出しをインターセプトできる。
const handler: ProxyHandler<any> = {
get(target, prop) {
console.log(`Accessing ${String(prop)}`);
return Reflect.get(target, prop);
},
set(target, prop, value) {
console.log(`Setting ${String(prop)} = ${value}`);
return Reflect.set(target, prop, value);
},
};
const user = new Proxy({ name: 'Alice' }, handler);
user.name; // "Accessing name"
user.name = 'Bob'; // "Setting name = Bob"
Vue 3 のリアクティビティシステムは Proxy で実装されている。
Decorator パターンとの違い
| パターン | 目的 | インターフェース |
|---|---|---|
| Proxy | アクセス制御、遅延初期化 | Real Subject と同じ |
| Decorator | 機能の追加 (重ねがけ可能) | Real Subject と同じ |
Proxy は「アクセスを制御する」、Decorator は「機能を追加する」。実装は似ているが意図が異なる。
実務での活用
- API Gateway: Lambda の前段に配置される Proxy (認証、レート制限、キャッシュ)
- CloudFront: オリジンサーバーの前段に配置されるキャッシュプロキシ
- RDS Proxy: Lambda と RDS の間に配置される接続プーリングプロキシ
Proxy パターンの理解を深めるには関連書籍が参考になる。