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

 

posted @ 2023-04-21 14:21  格局打得开  阅读(55)  评论(0)    收藏  举报