[go] 代理模式

简介: [go] 代理模式

代理模式


为另一个对象提供一个替身或占位符以控制对这个对象的访问。


模型说明



  • 服务接口(Service Interface)声明了服务接口。代理必须遵循该接口才能伪装成服务对象。
  • 服务(Service)类提供了一些实用的业务逻辑。
  • 代理(Proxy)类包含一个指向服务对象的引用成员变量。代理完成其任务 (例如延迟初始化、 记录日志、 访问控制和缓存等) 后会将请求传递给服务对象。
  • 通常情况下, 代理会对其服务对象的整个生命周期进行管理。
  • 客户端 (Client) 能通过同一接口与服务或代理进行交互, 所以你可在一切需要服务对象的代码中使用代理。

优缺点


1.优点


  • 你可以在客户端毫无察觉的情况下控制服务对象。
  • 如果客户端对服务对象的生命周期没有特殊要求,你可以对生命周期进行管理。
  • 即使服务对象还未准备好或不存在,代理也可以正常工作。
  • 开闭原则:你可以在不对服务或客户端做出修改的情况下创建新代理。


2.缺点


  • 代码可能会变得复杂,因为需要新建许多类。
  • 服务响应可能会延迟。


使用场景


  • 延迟初始化(虚拟代理)。如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可使用代理模式。
  • 访问控制(保护代理)。如果你只希望特定客户端使用服务对象,这里的对象可以是操作系统中非常重要的部分,而客户端则是各种已启动的程序(包括恶意程序),此时可使用代理模式。
  • 本地执行远程服务(远程代理)。适用于服务对象位于远程服务器上的情形。
  • 记录日志请求(日志记录代理)。适用于当你需要保存对于服务对象的请求历史记录时。
  • 缓存请求结果(缓存代理)。适用于需要缓存客户请求结果并对缓存生命周期进行管理时,特别是当返回结果的体积非常大时。
  • 智能引用。可在没有客户端使用某个重量级对象时立即销毁该对象。


参考代码


我们用常见的代理中间件 nginx 来做一个例子


  • 提供了对应用程序服务器的受控访问权限。
  • 可限制速度。
  • 可缓存请求。


serverI.go(service 接口)


package main
type server interface {
 handleRequest(string, string) (int, string)
}


application.go(真实的服务)


package main
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 Ok"
}


nginx.go(代理)


package main
type Nginx struct {
 application       *Application
 maxAllowedRequest int
 rateLimiter       map[string]int
}
func newNginxServer() *Nginx {
 return &Nginx{
  application:       &Application{},
  maxAllowedRequest: 2,
  rateLimiter:       make(map[string]int),
 }
}
func (n *Nginx) handleRequest(url, method string) (int, string) {
 allowed := n.checkRateLimiting(url)
 if !allowed {
  return 403, "Not Allowed"
 }
 return n.application.handleRequest(url, method)
}
func (n *Nginx) checkRateLimiting(url string) bool {
 if n.rateLimiter[url] == 0 {
  n.rateLimiter[url] = 1
 }
 if n.rateLimiter[url] > n.maxAllowedRequest {
  return false
 }
 n.rateLimiter[url] = n.rateLimiter[url] + 1
 return true
}


main.go(客户端)


package main
import "fmt"
func main() {
 nginxServer := newNginxServer()
 appStatusURL := "/app/status"
 createuserURL := "/create/user"
 httpCode, body := nginxServer.handleRequest(appStatusURL, "GET")
 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
 httpCode, body = nginxServer.handleRequest(appStatusURL, "GET")
 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
 httpCode, body = nginxServer.handleRequest(appStatusURL, "GET")
 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
 httpCode, body = nginxServer.handleRequest(createuserURL, "POST")
 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
 httpCode, body = nginxServer.handleRequest(createuserURL, "GET")
 fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
}


output:


Url: /app/status
HttpCode: 200
Body: Ok
Url: /app/status
HttpCode: 200
Body: Ok
Url: /app/status
HttpCode: 403
Body: Not Allowed
Url: /app/status
HttpCode: 201
Body: User Created
Url: /app/status
HttpCode: 404
Body: Not Ok
相关文章
|
设计模式 缓存 Go
Go语言实现设计模式之代理模式
代理模式是一种常用的设计模式,它通过引入代理对象来控制对真实对象的访问。本文将详细介绍代理模式的概念和原理,并使用Go语言实现一个示例,以帮助读者更好地理解该设计模式的应用。
178 0
|
5月前
|
设计模式 Go 网络安全
[设计模式 Go实现] 结构型~代理模式
[设计模式 Go实现] 结构型~代理模式
|
设计模式 程序员 Go
Go设计模式(11)-代理模式
从本篇文章开始讲解结构型模式,结构型模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题。
|
6天前
|
Go
Go 语言循环语句
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。
14 1
|
5天前
|
Go 开发者
探索Go语言的并发之美
在Go语言的世界里,"并发"不仅仅是一个特性,它是一种哲学。本文将带你领略Go语言中goroutine和channel的魔力,揭示如何通过Go的并发机制来构建高效、可靠的系统。我们将通过一个简单的示例,展示如何利用Go的并发特性来解决实际问题,让你的程序像Go一样,轻盈而强大。
|
6天前
|
JSON Go API
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
|
6天前
|
Go
go语言创建字典
go语言创建字典
|
7天前
|
安全 Go 数据处理
探索Go语言的并发之美:Goroutines与Channels
在Go语言的世界里,"并发"不仅仅是一个概念,它是一种生活的方式。本文将带你领略Go语言中Goroutines和Channels的魔力,它们是如何让并发编程变得既简单又高效。我们将通过一个简单的示例,展示如何使用这些工具来构建一个高性能的网络服务。
|
7天前
|
关系型数据库 Go 数据处理
高效数据迁移:使用Go语言优化ETL流程
在本文中,我们将探索Go语言在处理大规模数据迁移任务中的独特优势,以及如何通过Go语言的并发特性来优化数据提取、转换和加载(ETL)流程。不同于其他摘要,本文不仅展示了Go语言在ETL过程中的应用,还提供了实用的代码示例和性能对比分析。
|
7天前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19