持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
Go设计模式“金旋风”——代理模式
在代理模式中,代理类代理被代理目标类的功能。我们常说结构型设计模式,代理模式就是一种结构性设计模式。在代理模式中,代理控制着原对象的访问,并允许在将请求提交给对象的前后进行一些处理。
为什么会有代理模式?
如果我们的程序中有一个资源消耗可能会很大的对象,但是有可能用不到,我们就要当要使用它的时候在创建,而不是一开始就创建,而很多地方都可能需要用到创建该对象的代码,为了避免代码重复,我们使用代理模式。
我们使用代理模式,让代理类去创建代理对象为客户端请求,因为代理拥有原类的功能,甚至还能提供更多功能。
代理模式实例
接下来演示Bilibili如何使用代理模式实现缓存的:我们在使用APP的时候,使用代理类实现下载API相同的接口,并使用下载器使用下载API实现下载功能,但是代理类也会根据下载记录返回缓存。
package main
import "fmt"
type Movie struct {
name string
cached bool
}
type BilibiliDownloaderAPI interface {
DownloadMovie(m *Movie)
}
type BilibiliDownloader struct {
BilibiliDownloaderAPI
}
func (b *BilibiliDownloader) DownloadMovie(m *Movie) {
fmt.Println("下载视频中" + m.name + "...")
}
type Proxy struct {
downloaderAPI BilibiliDownloaderAPI
}
func CreateProxy(downloaderAPI BilibiliDownloaderAPI) BilibiliDownloaderAPI {
return &Proxy{downloaderAPI}
}
func (p *Proxy) DownloadMovie(m *Movie) {
if m.cached == false {
p.downloaderAPI.DownloadMovie(m)
m.cached = true
} else {
p.LoadingCache(m)
}
}
func (p *Proxy) LoadingCache(m *Movie) {
fmt.Println("加载" + m.name + "缓存...")
}
func main() {
movie := Movie{name: "一只小仓鼠的故事", cached: false}
proxy := CreateProxy(new(BilibiliDownloader))
proxy.DownloadMovie(&movie)
proxy.DownloadMovie(&movie)
}
代理模式应用场景
- 虚拟代理:如若我们有一个及其消耗系统资源的对象,他不一定会被使用,我们可以使用代理模式,让对象的初始化延迟。
- 保护代理:如果你只希望某个程序只作用于操作系统中重要部分,比如病毒,可以使用代理模式。使得仅在客户端满足要求时将请求传递给服务对象。
- 远程代理:当服务对象位于远程服务器上时可使用。代理通过网络传递客户端请求,处理所有与网络进行通讯的细节。
- 日志代理:当你想保存服务对象的请求历史时可以使用。代理可以输出在服务通过代理之前的每一个请求日志。
代理模式的优缺点
优点:
- 能够在客户端不察觉的情况下控制服务对象
- 符合开闭原则
- 代理能够在服务对象未准备好时正常工作。
缺点:
- 代码可能会变得复杂
- 服务可能出现延迟