代理模式
简介
简介
代理模式(Proxy Pattern)是指出于某些原因,需要给某个对象提供一个代理对象的设计模式,用于控制对该对象的访问。
使用场景
常见使用场景:
- 延迟初始化。如果开发者有一个偶尔使用的重量级服务对象,一直使该对象保持运行会消耗系统资源,则可以使用代理模式
- 访问控制。如果开发者只希望特定客户端使用服务对象
优点
- 安全
- 避免低使用率的巨型对象对系统资源的持续占用
缺点
如果一部分客户端直接访问真实的服务对象,而另一部分访问代理对象,则可能导致不同步的问题。
示例
Go
package proxy
type Server interface {
HandleRequest(string, string) (int, string)
}
type Apache struct {
Application *Application
maxAllowedRequest int
rateLimiter map[string]int
}
func NewApacheServer() *Apache {
return &Apache{
Application: &Application{},
maxAllowedRequest: 2,
rateLimiter: make(map[string]int),
}
}
func (a *Apache) HandleRequest(url, method string) (int, string) {
allowed := a.CheckRateLimit(url)
if !allowed {
return 403, "Not Allowed"
}
return a.Application.HandleRequest(url, method)
}
func (a *Apache) CheckRateLimit(url string) bool {
if a.rateLimiter[url] == 0 {
a.rateLimiter[url] = 1
}
if a.rateLimiter[url] > a.maxAllowedRequest {
return false
}
a.rateLimiter[url] += 1
return true
}
type Application struct{}
func (a *Application) HandleRequest(url, method string) (int, string) {
if url == "/user/status" && method == "GET" {
return 200, "OK"
}
if url == "/user/login" && method == "POST" {
return 201, "User Login"
}
return 404, "Not OK"
}
client
package proxy
import "testing"
func TestProxy(t *testing.T) {
server := NewApacheServer()
url1 := "/user/status"
url2 := "/user/login"
httpCode, body := server.HandleRequest(url1, "GET")
t.Logf("Url: %s, Code: %d, Body: %s", url1, httpCode, body)
httpCode, body = server.HandleRequest(url2, "POST")
t.Logf("Url: %s, Code: %d, Body: %s", url2, httpCode, body)
}