1. パターンの意図
プロキシ(Proxy)パターンは、
本物のオブジェクト(RealSubject)へのアクセスを代理するオブジェクトを提供するデザインパターンです。
解決する問題
- オブジェクトの生成やアクセスにコストが高い(遅延生成したい)
- セキュリティーのためアクセス制御したい
- ネットワーク越しのリモート呼び出しを隠蔽したい
ポイント
- Subject:共通インターフェース
- RealSubject:本物の処理を行うクラス
- Proxy:RealSubject と同じインターフェースを持ち、呼び出しを委譲(+制御やキャッシュを追加)
2. UML 図
3. Flutter / Dart 実装例
Subject
abstract class Image {
void display();
}
RealSubject
class RealImage implements Image {
final String filename;
RealImage(this.filename) {
_loadFromDisk(filename);
}
void _loadFromDisk(String filename) {
print("Loading $filename from disk...");
}
@override
void display() {
print("Displaying $filename");
}
}
Proxy
class ProxyImage implements Image {
RealImage? _realImage;
final String filename;
ProxyImage(this.filename);
@override
void display() {
_realImage ??= RealImage(filename); // 遅延ロード
_realImage!.display();
}
}
利用例
void main() {
Image image = ProxyImage("anna.png");
// 初回はロードが走る
image.display();
// 2回目以降はキャッシュ利用
image.display();
}
出力:
Loading anna.png from disk...
Displaying anna.png
Displaying anna.png
4. Android / Kotlin 実装例
Subject
interface Image {
fun display()
}
RealSubject
class RealImage(private val filename: String) : Image {
init {
loadFromDisk(filename)
}
private fun loadFromDisk(filename: String) {
println("Loading $filename from disk...")
}
override fun display() {
println("Displaying $filename")
}
}
Proxy
class ProxyImage(private val filename: String) : Image {
private var realImage: RealImage? = null
override fun display() {
if (realImage == null) {
realImage = RealImage(filename)
}
realImage?.display()
}
}
利用例
fun main() {
val image: Image = ProxyImage("anna.png")
image.display() // 初回はロードあり
image.display() // 2回目はキャッシュ利用
}
5. プロキシの種類
- Virtual Proxy:コストの高いオブジェクトを遅延生成(例:画像やDB接続)
- Protection Proxy:アクセス制御(例:ユーザー権限に応じて呼び出し可否を制御)
- Remote Proxy:リモートオブジェクトをローカルから操作(例:gRPC, REST API 呼び出し)
- Cache Proxy:結果をキャッシュして効率化(例:Webキャッシュ、DBクエリキャッシュ)
6. 実務ユースケース
Flutter
- 遅延ロードの画像/リソースラッパ
- 認証状態に応じたサービス呼び出し制御
- Provider や Repository に Proxy を噛ませてキャッシュ管理
Android / Kotlin
- Retrofit + OkHttp の Interceptor による Proxy 的挙動
- Room DB アクセスの Proxy ラッパ
- 権限管理付き Repository(Protection Proxy)
7. Decorator との違い
| 項目 | Proxy | Decorator |
|---|---|---|
| 共通点 | 同じインターフェースを持ち、呼び出しを委譲 | 同じインターフェースを持ち、呼び出しを委譲 |
| 目的 | アクセス制御・遅延生成 | 機能追加・拡張 |
| 例 | Virtual Proxy = 遅延ロード、Protection Proxy = 認可 | コーヒーにミルク/砂糖追加、Padding(Text) |
まとめ
- Proxy パターンは「代理人」
- 本物のオブジェクトへのアクセスをコントロールする
- Flutter/Android ではキャッシュ・遅延ロード・アクセス制御の場面でよく使われる
- Decorator が“拡張”、Proxy が“制御” というのが最大の違い