大家好, 我是大帥哥,由于最近又變帥了, 所以我決定由我的代理人小帥哥來寫這篇博客,不過內容可以放心,還是由我來完成,小帥哥的活就是將我的內容替我發出來罷了。
&_& 還是進入正題吧, 今天這篇博客我們繼續來學習設計模式, 在學習了上面幾個設計模式以后大家有無發現設計模式其實很簡單, 難道地方是什么時候選用適合的模式, 這也是設計模式最重要的地方, 不能我們學會的設計模式就能夠亂用。 明白就好…… 下面我們就開始介紹1個新的設計模式-代理模式。
甚么是代碼模式? 其實文章剛開始的段子其實不是尋開心的,其實那就是現實生活中的1個代理模式, 你和我之前通過1個中間人來完成通訊, 其實就這么簡單。 雖然簡單, 我們還是有必要來看1下人家總結的定義:
為其他對象提供1種代理以控制對這個對象的訪問。在某些情況下,1個對象不合適或不能直接援用另外一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
怎樣理解呢? 網上有1個段子解釋的很好, 比如你喜歡1個妹子, 不好意思跟人家開口, 這時候候你可能就通過她舍友來表達你的傾慕了。 再來看看代理模式的類圖吧,通常情況下, 看完定義迷迷糊糊的, 看完類圖可能就糊糊的, 等看完代碼示例, 就完全明白了。
從圖中可以看到, 代理模式共有4個角色, 其中1個還是抽象的。
Client
就是上面那個段子中的你, 你是行動的主導者。Subject
是代理人和被代理的抽象接口RealSubject
被代理的對象, 也就是上面的妹子Proxy
代理者, 對應上面的妹子室友
不過, 仔細看看類圖, 我開始懷疑代理模式的必要性了。 有必要嗎? 我直接去調用RealSubject
不就好了, 還這么麻煩, 通過1個代理來調用, 這不就是脫了褲子放屁嗎? 其實不然, 很多情況下, 真實的對象是我們訪問不到的,或是提供者不想讓我們訪問到, 這個時候我們就需要1個代理來幫我們完成。舉個例子? 很簡單, 我們訪問1個網站, 數據是否是都放數據庫里? 但是網站的提供這不允許我們直接操作數據庫, 這個時候就提供了1個頁面, 我們通過頁面來間接的往數據庫里插入數據。
好了, 文字的東西不多扯了, 下面我們就用代碼來演示1下吧, 在今天我代碼中, 我們來摹擬1下平時我們使用github的進程,我們在從github上clone項目的時候1般都是通過命令行來完成吧, 其實這個命令行完全可以看做是github的1個代理。
根據上面的類圖, 我們首先要提供1個抽象的接口來規范代理和對象的行動
type Git interface {
Clone(url string) bool
}
ok, 很簡單, 只有1個Clone
方法,表示我們要從git源來clone項目。 下面我們接著來實現1下真實對象, 也就是Github
。
type GitHub struct{}
func (p GitHub) Clone(url string) bool {
if strings.HasPrefix(url, "https") {
fmt.Println("clone from " + url)
return true
}
fmt.Println("failed to clone from " + url)
return false
}
GitHub
實現了Clone
方法, 所以它實現了Git
接口,至于Clone
方法中的邏輯, 我們就不用關心了, 還有1個重要的角色我們還沒看, 來看看代理怎樣寫吧。
type GitBash struct {
Gitcmd Git
}
func (p GitBash) Clone(url string) bool {
return p.Gitcmd.Clone(url)
}
這是我們的命令行, 它持有1個Git
類型的變量, 并且他還是先了Clone
方法, 我們在調用Clone
方法的時候,實際上是間接的調用了這個Git
類型變量的Clone
方法,這就是代理!
還剩下最后1個角色, 那就是我們Coder
自己了, 我們自己就隨便多了
type Coder struct{}
func (p Coder) GetCode(url string) {
gitBash := GetGit(1)
if gitBash.Clone(url) {
fmt.Println("success")
} else {
fmt.Println("failed")
}
}
GetGit
是啥? 其實就是提供者提供給我們的可調用的接口。
func GetGit(t int) Git {
if t == 1 {
return GitBash{Gitcmd: GitHub{}}
}
return nil // 可能還有其他的git源
}
首先,我們知道我們是要從GitHub
上clone項目, 所以我們告知代理要從GitHub
上給我clone項目,別跑GitLab
上去了。接下來我們就調用代理的Clone
方法,通過前面的代碼我們完全可以理解,這里面肯定是調用了GitHub
的Clone
方法。 最后我們再來看看運行結果。
完善, 現在理解甚么是代理模式了吧。代理模式其實最主要的用處就是當我們沒法直接訪問1個對象的時候, 通過代理的方式來完成對對象的訪問。代理模式具有高擴大性,假設我們需要從GitLab
上,只需要提供者添加1個GitLab
對象, 然后我們調用GetGit
時指定使用GitLab
就能夠了。
今天的博客很簡單,其實模式的代碼都是很簡單的,不要被設計模式這4個字嚇到。 我們6月份再見!
代碼放github上了,歡迎star: https://github.com/qibin0506/go-designpattern