Proxy パターン
オブジェクトへのアクセスを代理オブジェクトが仲介し、アクセス制御やキャッシュなどの付加機能を提供するパターン
設計パターン基礎
Proxy パターンとは
Proxy パターンは、本物のオブジェクト (Real Subject) の前に代理オブジェクト (Proxy) を配置し、アクセス制御、遅延初期化、キャッシュ、ログ記録などの付加機能を透過的に提供する GoF デザインパターンである。クライアントは Proxy と Real Subject を区別せずに使える。
Proxy の種類
Proxy の種類を以下にまとめる。
| 種類 | 目的 | 例 |
|---|---|---|
| キャッシュプロキシ | 結果をキャッシュして高速化 | API レスポンスのキャッシュ |
| 保護プロキシ | アクセス権限をチェック | 認証・認可の検証 |
| 仮想プロキシ | 重いオブジェクトの遅延初期化 | 画像の遅延読み込み |
| ログプロキシ | アクセスを記録 | API 呼び出しのログ |
| リモートプロキシ | リモートオブジェクトをローカルに見せる | gRPC クライアント |
TypeScript での実装
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 パターンとの違い
Decorator パターンとの違いを以下にまとめる。
| パターン | 目的 | インターフェース |
|---|---|---|
| Proxy | アクセス制御、遅延初期化 | Real Subject と同じ |
| Decorator | 機能の追加 (重ねがけ可能) | Real Subject と同じ |
Proxy は「アクセスを制御する」、Decorator は「機能を追加する」。実装は似ているが意図が異なる。
実務での活用
- API Gateway: Lambda の前段に配置される Proxy (認証、レート制限、キャッシュ)
- CloudFront: オリジンサーバーの前段に配置されるキャッシュプロキシ
- RDS Proxy: Lambda と RDS の間に配置される接続プーリングプロキシ
Proxy パターンの理解を深めるには関連書籍が参考になる。
この記事は役に立ちましたか?
関連用語
デザインパターン
ソフトウェア設計で繰り返し現れる問題に対する再利用可能な解決策のカタログ
Decorator パターン実装
既存オブジェクトの振る舞いを動的に拡張し、継承を使わずに機能を追加するデザインパターン
キャッシュ
頻繁にアクセスされるデータを高速なストレージに保存し、読み取り性能を向上させる手法
Null Object パターン
null チェックの代わりに、何もしないオブジェクトを使って条件分岐を排除するデザインパターン
S3
AWS のオブジェクトストレージサービスで、無制限のデータを高い耐久性で保存する
Builder パターン
複雑なオブジェクトの生成をメソッドチェーンで段階的に構築するデザインパターン