代理模式
作为一种结构型的设计模式,因为某种原因,需要对访问的对象通过代理访问目标对象,访问对象不适合或者不能直接引用该目标对象,代理就成为访问对象和目标对象的中介。
结构
- 1.抽象主题(Subject)类。通过接口或抽象类声明真实主题和代理对象实现的业务方法。
- 2.真实主题(Real Subject)类。实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
- 3.代理(Proxy)类。提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
优缺点
- 优点
1.保护目标对象,访问对象只能通过代理访问到目标对象。
2.代理对象可扩展目标对象的功能。
3.通过代理,分离访问对象与目标对象的直接接触,降低耦合,增加扩展。
- 缺点
1.代理模式会造成系统设计中类的数量增加。
2.在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢。
3.增加了系统的复杂度。
适用场景
- 1.远程代理。可以隐藏一个对象存在于不同地址空间的事实,如 nginx。
- 2.Copy-on-Write 代理。linux内核中大量使用。
- 3.Cache代理。
- 4.防火墙(Firewall)代理。
代码实现
package main
import "fmt"
/*
业务场景:
- 通过nginx代理web请求,client <-> nginx <-> realServer
- 通常在代理层,我们也可以完成一些额外处理,如限流,认证,负载均衡等,本case主要目的演示proxy模式的应用,额外功能见限流处理
*/
// 1.抽象服务,声明方法,代理类和真实服务类需要实现该接口
type Server interface {
HandleRequest(url string, method string) (code int, msg string)
}
// 2.real server, 实现Server接口,实际请求处理
type Application struct {
host string
port int
}
func NewApplication() *Application {
return &Application{"0.0.0.0", 8001}
}
func (r *Application) handleRequest(url string, method string) (code int, msg string) {
// 路由处理
if url == "/app/status" && method == "GET" {
return 200, "OK"
}
if url == "/create/user" && method == "POST" {
return 201, "User Created."
}
return 404, "Not Found."
}
// 3.proxy,实现Server接口,代理客户端请求,转发给real server,另简单实现限流功能
type NginxServer struct {
application *Application
maxAllowReq int
rateLimiter map[string]int
}
func NewNginxServer(allowReq int) *NginxServer {
return &NginxServer{
application: NewApplication(),
maxAllowReq: allowReq,
rateLimiter: make(map[string]int),
}
}
func (r *NginxServer) HandleRequest(url, method string) (code int, msg string) {
isAllowed := r.checkRateLimiter(url)
if !isAllowed {
return 403, "Not Allowed."
}
// forward to real server
return r.application.handleRequest(url, method)
}
func (r *NginxServer) checkRateLimiter(url string) bool {
if r.rateLimiter[url] == 0 {
r.rateLimiter[url] = 1
}
if r.rateLimiter[url] > r.maxAllowReq {
return false
}
r.rateLimiter[url]++
return true
}
// client
func main() {
ngx := NewNginxServer(2)
appStatusURL := "/app/status"
createuserURL := "/create/user"
httpCode, body := ngx.HandleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = ngx.HandleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = ngx.HandleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = ngx.HandleRequest(createuserURL, "POST")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = ngx.HandleRequest(createuserURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
}
参考文章:
标签:body,string,url,优缺点,代理,httpCode,golang,对象,设计模式 From: https://www.cnblogs.com/davis12/p/17469978.html