1. 什么是代理模式
代理模式是一种结构型设计模式,它通过引入一个代理对象来控制对另一个对象的访问。代理对象可以在客户端和目标对象之间添加额外的功能,如延迟加载、访问控制、日志记录等。
2. 为什么需要代理模式
代理模式的核心价值在于在不改变原始对象(目标对象)代码的前提下,增加额外的控制和功能。它像一个中介,隔离了客户端和真实对象,并在中间“做手脚”。
3. 代理模式的实现 (Go)
我们用 Go 实现一个保护代理的例子。假设我们有一个 Web 服务器,希望通过一个 Nginx 代理来限制用户的访问速率。
- 客户端、代理和真实服务都应遵循同一个接口,这样代理才能“伪装”成真实服务。
1 2 3 4
| type Server interface { HandleRequest(url, method string) (int, string) }
|
- 创建真实服务 (RealSubject)
这是我们真正要保护的后端应用。
1 2 3 4 5 6 7 8 9 10 11 12
| type Application struct{}
func (a *Application) HandleRequest(url, method string) (int, string) { if url == "/app/status" && method == "GET" { return 200, "Ok" } if url == "/create/user" && method == "POST" { return 201, "User Created" } return 404, "Not Found" }
|
- 创建代理 (Proxy)
Nginx 代理持有对真实服务的引用,并在处理请求前增加了速率限制的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import "fmt"
type Nginx struct { application *Application maxAllowedReq int rateLimiter map[string]int }
func NewNginxServer() *Nginx { return &Nginx{ application: &Application{}, maxAllowedReq: 2, rateLimiter: make(map[string]int), } }
func (n *Nginx) checkRateLimit(url string) bool { n.rateLimiter[url]++ if n.rateLimiter[url] > n.maxAllowedReq { return false } return true }
func (n *Nginx) HandleRequest(url, method string) (int, string) { if !n.checkRateLimit(url) { return 429, "Too Many Requests" }
return n.application.HandleRequest(url, method) }
|
- 客户端调用
客户端只与代理(Nginx)交互,并不知道真实服务(Application)的存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| func main() { nginx := NewNginxServer()
code, body := nginx.HandleRequest("/app/status", "GET") fmt.Printf("Url: /app/status, Code: %d, Body: %s\n", code, body)
code, body = nginx.HandleRequest("/app/status", "GET") fmt.Printf("Url: /app/status, Code: %d, Body: %s\n", code, body)
code, body = nginx.HandleRequest("/app/status", "GET") fmt.Printf("Url: /app/status, Code: %d, Body: %s\n", code, body) }
|
类图
classDiagram
class Client
class Server {
<<interface>>
+HandleRequest(url, method)
}
class Application {
+HandleRequest(url, method)
}
class Nginx {
-application: *Application
-maxAllowedReq: int
-rateLimiter: map
+HandleRequest(url, method)
-checkRateLimit(url): bool
}
Client --> Server : uses
Server <|.. Application : implements
Server <|.. Nginx : implements
Nginx o-- Application : aggregates