用一個同介面的替身站在真實物件前面,控制對它的存取——延遲建立、權限檢查、快取或遠端轉發——而 client 感覺不到差別。
🧠 When to Use
TIP
訊號:你想在「呼叫真實物件」前後插入控制(先檢查權限、先看快取、用到才載入),但不想改 client、也不想改真實物件的介面。
- virtual:建立成本高,想延遲到真正用到時才初始化。
- protection:呼叫前要做權限 / 條件檢查。
- remote / caching:把呼叫轉發到遠端,或快取結果省重複計算。
⚖️ Structure & Variants
Virtual Proxy — 延遲載入
interface Image { fun render() }
// 真實物件:建立成本高(讀檔、解碼)
class RealImage(private val path: String) : Image {
init { /* 從磁碟載入、解碼,很貴 */ }
override fun render() { /* draw pixels */ }
}
// Proxy:同介面,真正 render 時才建立 RealImage
class ImageProxy(private val path: String) : Image {
private val real: RealImage by lazy { RealImage(path) }
override fun render() = real.render()
}
val img: Image = ImageProxy("big.png") // 此時尚未載入
img.render() // 此刻才真的載入- 關鍵:Proxy 實作同一介面,client 拿到的就像真實物件。
Protection Proxy — 權限控制
- 呼叫真實物件前先檢查身分 / 權限,未通過就拋例外或回傳預設值。
- 把存取控制集中在 proxy,真實物件保持單純、專注本業。
和 Decorator / Adapter 的差別
⚠️ Misuse & Anti-patterns
- 在 Proxy 裡加功能而非控存取:那其實是 Decorator;混淆會讓意圖模糊難維護。
- Proxy 改了介面:一旦簽章變了就不再能透明替換真實物件,那是 Adapter。
- 隱藏成本變陷阱:virtual / remote proxy 把昂貴或會失敗的呼叫藏在普通方法後,呼叫端易低估延遲與錯誤面。
🔑 Takeaways
- 解決的是「對真實物件的存取需要控制」:延遲、權限、遠端、快取。
- 成立前提:Proxy 實作同一介面,才能對 client 透明替換真實物件。
- 和 Decorator(加強行為)、Adapter(轉介面)都是「包一層」,Proxy 的意圖是控存取。
No notes yet — jot your takeaways or Q&A here.