实践GoF的设计模式:代理模式

摘要:代理模式为一个对象提供一种代理以控制对该对象的访问。

本文分享自华为云社区《【Go实现】实践GoF的23种设计模式:代理模式》,作者:元闰子 。

我们提供的服务有:成都网站制作、成都网站建设、微信公众号开发、网站优化、网站认证、布尔津ssl等。为超过千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的布尔津网站制作公司

简介

GoF 对代理模式(Proxy Pattern)的定义如下:

Provide a surrogate or placeholder for another object to control access to it.

也即,代理模式为一个对象提供一种代理以控制对该对象的访问。

它是一个使用率非常高的设计模式,在现实生活中,也是很常见。比如,演唱会门票黄牛。假设你需要看一场演唱会,但官网上门票已经售罄,于是就当天到现场通过黄牛高价买了一张。在这个例子中,黄牛就相当于演唱会门票的代理,在正式渠道无法购买门票的情况下,你通过代理完成了该目标。

从演唱会门票的例子我们也能看出,使用代理模式的关键在于,当 Client 不方便直接访问一个对象时,提供一个代理对象控制该对象的访问。Client 实际上访问的是代理对象,代理对象会将 Client 的请求转给本体对象去处理。

UML 结构

场景上下文

简单的分布式应用系统(示例代码工程)中,db 模块用来存储服务注册和监控信息,它是一个 key-value 数据库。为了提升访问数据库的性能,我们决定为它新增一层缓存:

另外,我们希望客户端在使用数据库时,并不感知缓存的存在,这些,代理模式可以做到。

代码实现

// demo/db/cache.go
package db
// 关键点1: 定义代理对象,实现被代理对象的接口
type CacheProxy struct {
// 关键点2: 组合被代理对象,这里应该是抽象接口,提升可扩展性
 db    Db
    cache sync.Map// key为tableName,value为sync.Map[key: primaryId, value: interface{}]
    hit   int
 missint
}
// 关键点3: 在具体接口实现上,嵌入代理本身的逻辑
func (c *CacheProxy) Query(tableName string, primaryKey interface{}, result interface{}) error {
    cache, ok := c.cache.Load(tableName)
if ok {
if record, ok := cache.(*sync.Map).Load(primaryKey); ok {
 c.hit++
            result= record
return nil
 }
 }
 c.miss++
 if err := c.db.Query(tableName, primaryKey, result); err != nil {
return err
 }
 cache.(*sync.Map).Store(primaryKey, result)
return nil
}
func (c*CacheProxy) Insert(tableName string, primaryKey interface{}, record interface{}) error {
if err := c.db.Insert(tableName, primaryKey, record); err != nil {
return err
 }
    cache, ok := c.cache.Load(tableName)
if !ok {
return nil
 }
 cache.(*sync.Map).Store(primaryKey, record)
return nil
}
...
// 关键点4: 代理也可以有自己特有方法,提供一些辅助的功能
func (c *CacheProxy) Hit() int {
return c.hit
}
func (c*CacheProxy) Miss() int {
return c.miss
}
...

标题名称:实践GoF的设计模式:代理模式
链接地址:http://scyanting.com/article/dsoicoe.html