GoLang设计模式26 - 代理模式(结构型)
代理模式是一种结构型设计模式。这种模式建议在访问对象时,添加一个额外的控制层,以便更灵活智能得对访问进行管理。
在这种模式中,会实现主对象的接口创建一个新的代理类。这让我们在执行主对象的逻辑前可以做一些额外的行为。看两个例子吧:
1. 信用卡可以视为是银行账户的代理。它的操作逻辑和银行账户相同,但却更容易使用。
2. 诸如Nginx这样的web服务器可以视为是应用服务器的代理,它可以起到如下的作用:
* 控制对应用服务器的访问,比如执行限流
* 做一些额外的动作,比如做一些缓存
看下代理模式的UML类图:

简单介绍下类图中的成员:
* `Subject`: 代表了主对象类(`realSubject`)和代理类(`proxy`)都需要实现的接口
* `Proxy`: 代表了代理类,在代理类中会嵌入`realSubject`实例,在它自己做完对请求的处理后,会将请求传递给`realSubject`实例进行操作
* `RealSubject`: 主对象类,包含了真实的业务逻辑,在代理模式中被置于代理类之后
* `Client`: 场景类,和代理类及主对象类都进行交互,因为二者实现了相同的接口
下面是前面介绍的nginx和应用服务器的例子所对应的类图:

下面是代码:
server.go:
1 type server interface { 2 handleRequest(string, string) (int, string) 3 }
application.go
1 type application struct { 2 } 3 4 func (a *application) handleRequest(url, method string) (int, string) { 5 if url == "/app/status" && method == "GET" { 6 return 200, "Ok" 7 } 8 if url == "/create/user" && method == "POST" { 9 return 201, "User Created" 10 } 11 return 404, "Not Ok" 12 }
nginx.go
1 type nginx struct { 2 application *application 3 maxAllowedRequest int 4 rateLimiter map[string]int 5 } 6 7 func newNginxServer() *nginx { 8 return &nginx{ 9 application: &application{}, 10 maxAllowedRequest: 2, 11 rateLimiter: make(map[string]int), 12 } 13 } 14 15 func (n *nginx) handleRequest(url, method string) (int, string) { 16 allowed := n.checkRateLimiting(url) 17 if !allowed { 18 return 403, "Not Allowed" 19 } 20 return n.application.handleRequest(url, method) 21 } 22 23 func (n *nginx) checkRateLimiting(url string) bool { 24 if n.rateLimiter[url] == 0 { 25 n.rateLimiter[url] = 1 26 } 27 if n.rateLimiter[url] > n.maxAllowedRequest { 28 return false 29 } 30 n.rateLimiter[url] = n.rateLimiter[url] + 1 31 return true 32 }
main.go
1 func main() { 2 nginxServer := newNginxServer() 3 appStatusURL := "/app/status" 4 createUserURL := "/create/user" 5 httpCode, body := nginxServer.handleRequest(appStatusURL, "GET") 6 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body) 7 httpCode, body = nginxServer.handleRequest(appStatusURL, "GET") 8 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body) 9 httpCode, body = nginxServer.handleRequest(appStatusURL, "GET") 10 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body) 11 httpCode, body = nginxServer.handleRequest(createUserURL, "POST") 12 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body) 13 httpCode, body = nginxServer.handleRequest(createUserURL, "GET") 14 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body) 15 }
输出内容:
1 Url: /app/status 2 HttpCode: 200 3 Body: Ok 4 5 Url: /app/status 6 HttpCode: 200 7 Body: Ok 8 9 Url: /app/status 10 HttpCode: 403 11 Body: Not Allowed 12 13 Url: /app/status 14 HttpCode: 201 15 Body: User Created 16 17 Url: /app/status 18 HttpCode: 404 19 Body: Not Ok
浙公网安备 33010602011771号