结构型 代理模式

为什么需要代理模式

结构型的设计模式基本都是做的在不改变基本类的情况修修补补,或者增加功能。可能有个疑问,那为什么不直接在原来类的基础上直接增加呢?原因一般是这些新功能不直接和原来设计的类有关系,我们可以想象一个中间件用来统计接口(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

Previous
Next