1. design-patterns/

golang 代理模式讲解和代码示例

·284 字·2 分钟· loading
设计模式 设计模式 golang
demo007x
作者
demo007x
设计模式 - This article is part of a series.
Part : This Article

Go 代理模式讲解和代码示例
#

代理是一种结构型设计模式, 让你能提供真实服务对象的替代品给客户端使用。 代理接收客户端的请求并进行一些处理 (访问控制和缓存等), 然后再将请求传递给服务对象。

代理对象拥有和服务对象相同的接口, 这使得当其被传递给客户端时可与真实对象互换。

概念示例
#

Nginx 这样的 Web 服务器可充当应用程序服务器的代理:

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

server.go: 主体
#

package main

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

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
}

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"
}

main.go: 客户端代码
#

package main

import "fmt"

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

	httpCode, msg = nginxServer.handleRequest(appStatusURL, "GET")
	fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, msg)

	httpCode, msg = nginxServer.handleRequest(appStatusURL, "GET")
	fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, msg)

	httpCode, msg = nginxServer.handleRequest(createuserURL, "POST")
	fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, msg)

	httpCode, msg = nginxServer.handleRequest(createuserURL, "GET")
	fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, msg)
}

output.txt: 执行结果
#


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
设计模式 - This article is part of a series.
Part : This Article

Related

golang 原型模式讲解和代码示例
设计模式 设计模式 golang
原型是一种创建型设计模式, 使你能够复制对象, 甚至是复杂对象, 而又无需使代码依赖它们所属的类。所有的原型类都必须有一个通用的接口, 使得即使在对象所属的具体类未知的情况下也能复制对象。 原型对象可以生成自身的完整副本, 因为相同类的对象可以相互访问对方的私有成员变量。
golang 观察者模式讲解和代码示例
设计模式 设计模式 golang
观察者是一种行为设计模式, 允许一个对象将其状态的改变通知其他对象. 观察者模式提供了一种作用于任何实现了订阅者接口的对象的机制, 可对其事件进行订阅和取消订阅。
golang 中介者模式讲解和代码示例
设计模式 设计模式 golang
中介者是一种行为设计模式, 让程序组件通过特殊的中介者对象进行间接沟通, 达到减少组件之间依赖关系的目的。中介者能使得程序更易于修改和扩展, 而且能更方便地对独立的组件进行复用, 因为它们不再依赖于很多其他的类。