跳到主要内容

代理模式

简介

简介

代理模式(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)
}