1. 程式人生 > >設計模式-代理模式(Go語言描述)

設計模式-代理模式(Go語言描述)

大家好, 我是大帥哥,由於最近又變帥了, 所以我決定由我的代理人小帥哥來寫這篇部落格,不過內容可以放心,還是由我來完成,小帥哥的活就是將我的內容替我發出來罷了。

&_& 還是進入正題吧, 今天這篇部落格我們繼續來學習設計模式, 在學習了上面幾個設計模式之後大家有沒有發現設計模式其實很簡單, 難道地方是何時選用合適的模式, 這也是設計模式最重要的地方, 不能我們學會的設計模式就可以亂用。 明白就好…… 下面我們就開始介紹一個新的設計模式-代理模式

模式定義

什麼是程式碼模式? 其實文章剛開始的段子並不是尋開心的,其實那就是現實生活中的一個代理模式, 你和我之前通過一箇中間人來完成通訊, 其實就這麼簡單。 雖然簡單, 我們還是有必要來看一下人家總結的定義:

為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個物件不適合或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。

怎麼理解呢? 網上有一個段子解釋的很好, 比如你喜歡一個妹子, 不好意思跟人家開口, 這時候你可能就通過她舍友來表達你的愛慕了。 再來看看代理模式的類圖吧,通常情況下, 看完定義迷迷糊糊的, 看完類圖可能就糊糊的, 等看完程式碼示例, 就徹底明白了。

從圖中可以看到, 代理模式共有4個角色, 其中一個還是抽象的。

  1. Client 就是上面那個段子中的你, 你是行為的主導者。
  2. Subject
    是代理人和被代理的抽象介面
  3. RealSubject 被代理的物件, 也就是上面的妹子
  4. Proxy 代理者, 對應上面的妹子室友

不過, 仔細看看類圖, 我開始懷疑代理模式的必要性了。 有必要嗎? 我直接去呼叫RealSubject不就行了, 還這麼麻煩, 通過一個代理來呼叫, 這不就是脫了褲子放屁嗎? 其實不然, 很多情況下, 真實的物件是我們訪問不到的,或者是提供者不想讓我們訪問到, 這個時候我們就需要一個代理來幫我們完成。舉個例子? 很簡單, 我們訪問一個網站, 資料是不是都放資料庫裡? 但是網站的提供這不允許我們直接操作資料庫, 這個時候就提供了一個頁面, 我們通過頁面來間接的往資料庫裡插入資料。

程式碼演示

好了, 文字的東西不多扯了, 下面我們就用程式碼來演示一下吧, 在今天我程式碼中, 我們來模擬一下平時我們使用github的過程,我們在從github上clone專案的時候一般都是通過命令列來完成吧, 其實這個命令列完全可以看作是github的一個代理。

根據上面的類圖, 我們首先要提供一個抽象的介面來規範代理和物件的行為

type Git interface {
    Clone(url string) bool
}

ok, 很簡單, 只有一個Clone方法,表示我們要從git源來clone專案。 下面我們接著來實現一下真實物件, 也就是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方法中的邏輯, 我們就不用關心了, 還有一個重要的角色我們還沒看, 來看看代理怎麼寫吧。

type GitBash struct {
    Gitcmd Git
}

func (p GitBash) Clone(url string) bool {
    return p.Gitcmd.Clone(url)
}

這是我們的命令列, 它持有一個Git型別的變數, 並且他還是先了Clone方法, 我們在呼叫Clone方法的時候,其實是間接的呼叫了這個Git型別變數的Clone方法,這就是代理!

還剩下最後一個角色, 那就是我們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方法,通過前面的程式碼我們完全可以理解,這裡面肯定是呼叫了GitHubClone方法。 最後我們再來看看執行結果。

完美, 現在理解什麼是代理模式了吧。代理模式其實最主要的用途就是當我們無法直接訪問一個物件的時候, 通過代理的方式來完成對物件的訪問。代理模式具有高擴充套件性,假如我們需要從GitLab上,只需要提供者新增一個GitLab物件, 然後我們呼叫GetGit時指定使用GitLab就可以了。

今天的部落格很簡單,其真實模式的程式碼都是很簡單的,不要被設計模式這四個字嚇到。 我們6月份再見!

程式碼放github上了,歡迎star: https://github.com/qibin0506/go-designpattern