2023-08-25|閱讀時間 ‧ 約 5 分鐘

Golang - Design Pattern #10: 代理模式 (Proxy)

raw-image
你的門禁系統 🔐 是怎麼運作的?

嗨,各位!想像一下你住在一棟大樓里,每次有人要進來時,他們得先經過樓下的門禁員檢查,這樣才能確保大樓的安全。在程式設計的世界裡,我們也有類似的機制,那就是「代理模式 (Proxy Pattern)」!


代理是什麼?

代理模式允許我們控制對某個物件的訪問,這通常是為了在真正訪問這個物件之前或之後,加上一些額外的操作。換句話說,代理就像是一個中間人,負責協調你和目標物件之間的互動。


手把手教你怎麼做!


🖼️ 圖片的延遲載入

想像你正在開發一個圖片相關軟體,但你不希望一開始就載入所有圖片,因為這樣可能會浪費很多資源。你希望圖片能在真正需要時才被載入。這時,代理模式就派上用場了!


type Image interface {
Display() string
}

// 真實圖片,當它被載入時,就會占用記憶體資源
type RealImage struct {
filename string
}

func (ri *RealImage) Display() string {
return "Displaying " + ri.filename
}

// 代理圖片,當真正需要時才會載入真實圖片
type ProxyImage struct {
realImage *RealImage
filename string
}

func (pi *ProxyImage) Display() string {
if pi.realImage == nil {
pi.realImage = &RealImage{filename: pi.filename}
}
return pi.realImage.Display()
}

func main() {
image := &ProxyImage{filename: "test.jpg"}
fmt.Println(image.Display()) // 在這裡,圖片才被真正載入並顯示
}


💳 銀行帳號的安全檢查

你可能有一個銀行帳號,你不希望直接讓任何人都能夠取款。透過代理,我們可以加上一層安全檢查


// 銀行帳號 Interface​
type BankAccount interface {
Withdraw(amount int) string
}

// 真實銀行帳號
type RealAccount struct {
balance int
}

func (ra *RealAccount) Withdraw(amount int) string {
ra.balance -= amount
return fmt.Sprintf("Withdrew %d, balance now %d", amount, ra.balance)
}

// 代理銀行帳號加入安全檢查
type SecureAccountProxy struct {
realAccount *RealAccount
password string
}

func (sap *SecureAccountProxy) Withdraw(amount int, inputPassword string) string {
// 如果密碼輸入正確,則執行提款​
if sap.password != inputPassword {
return "密碼錯誤!"
}
return sap.realAccount.Withdraw(amount)
}

func main() {
account := &SecureAccountProxy{realAccount: &RealAccount{balance: 1000}, password: "secure123"}
fmt.Println(account.Withdraw(100, "wrongpass")) // 密碼錯誤!
fmt.Println(account.Withdraw(100, "secure123")) // (成功提款)
}


小結 🎉

代理模式提供了一個很好的方法,讓我們能夠控制對物件的訪問,並在需要時加上額外的操作。就像我們生活中的門禁員,確保每一次的互動都是安全和高效的。

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.