设计模式-代理模式(Go语言描述)

Posted 亓斌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-代理模式(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

以上是关于设计模式-代理模式(Go语言描述)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式-代理模式(Go语言描述)

代理设计模式详解C/Java/JS/Go/Python/TS不同语言实现

Go语言设计模式

[设计模式C++go]结构型模式:代理模式

[设计模式C++go]结构型模式:代理模式

[设计模式C++go]结构型模式:代理模式