结构型 代理模式
为什么需要代理模式
结构型的设计模式基本都是做的在不改变基本类的情况修修补补,或者增加功能。可能有个疑问,那为什么不直接在原来类的基础上直接增加呢?原因一般是这些新功能不直接和原来设计的类有关系,我们可以想象一个中间件用来统计接口(api)处理时间,这种这个统计时间的功能就和原来设计的类没什么直接关系。
代理模式的实现一般来说可以通过将需要被代理的类抽象出来一个interface,golang的interface是隐性实现的(也就是如果你的类实现了interface要求的函数,就默认你这个类实现了这个interface)这个为我们的工作带来了便利。
万一我们有大量的业务代码类需要实现他们的代理,那岂不是要求我们实现大量的代理接口?Java是通过反射语法实现InvocationHandler来实现这个需求的,关键词叫“动态代理”。因为我们不能要求具体的业务类去实现某个接口,java的设计是把具体业务类的route到invoke这个函数那里去。具体怎么实现这个route的,有了解的朋友请告诉我,十分感兴趣,源码那里只有一个interface。
看来我已经找到答案了,英文文献反而找不到,中文的倒是有https://www.cnblogs.com/songanwei/p/9390475.html。我觉得可以理解成java 客户端(也就是自己写的那一坨函数向jvm发请求的时候在request增加了invoke这一步,就是加了一个middleware)哈哈。与之对应Golang要实现动态代理我还真的没想到怎么弄,思路肯定是要想办法把generic的调用函数route到一个。哦,抱歉,go目前还没有范型。
扯了那么多,其实简单的proxy就够用了,golang的实现可没有那么复杂。
Proxy的Golang实现
go.mod
module proxy
go 1.13
proxy.go
package proxy
import "bytes"
type App struct {
}
func (a *App) Do() string {
return "App is running"
}
// We need to abstract out method first
type Iapp interface {
Do() string
}
type AppProxy struct {
app Iapp
}
func NewAppProxy(app Iapp) *AppProxy {
return &AppProxy{
app: app,
}
}
func (a *AppProxy) Do() string {
var buf bytes.Buffer
buf.WriteString("Before:")
// call here
buf.WriteString(a.app.Do())
buf.WriteString("#After")
return buf.String()
}
proxy_test.go
package proxy_test
import (
"proxy"
"testing"
)
func TestProxy(t *testing.T) {
myapp := &proxy.App{}
myProxyApp := proxy.NewAppProxy(myapp)
if myProxyApp.Do() != "Before:App is running#After" {
t.Fatal("Incorrect proxy implementation")
}
}
执行:
go test proxy -v