设计模式-08-代理模式

代理模式 在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能,常用在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、 日志

逻辑结构

Proxy

代码实现

代码路径:https://github.com/XBoom/DesignPatterns/tree/main/07_Proxy

  1. 需要被代理的行为是卖票

    1
    2
    3
    4
    // Seller 售票
    type Seller interface {
    Sell(name string)
    }
  2. 正常情况是火车站卖票

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // Station 火车站
    type Station struct {
    stock int //库存
    }

    func (station *Station) Sell(name string) {
    if station.stock > 0 {
    station.stock--
    fmt.Printf("%s purchased 1 ticket, %d remaining\n", name, station.stock)
    } else {
    fmt.Println("tickets are sold out")
    }
    }
  3. 而使用代理点卖票

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // StationProxy 火车代理点
    type StationProxy struct {
    station *Station // 持有一个火车站对象
    }

    func (proxy *StationProxy) Sell(name string) {
    if proxy.station.stock > 0 {
    proxy.station.stock--
    fmt.Printf("%s purchased 1 ticket, %d remaining\n", name, proxy.station.stock)
    } else {
    fmt.Println("tickets are sold out")
    }
    }

    var _ Seller = (*StationProxy)(nil)

单元测试

1
2
3
4
5
6
7
8
func TestStationProxy_sell(t *testing.T) {
station := &Station{3}
proxy := &StationProxy{station}
station.Sell("A")
proxy.Sell("B")
proxy.Sell("C")
proxy.Sell("D")
}

运行的结果是

1
2
3
4
A purchased 1 ticket, 2 remaining
B purchased 1 ticket, 1 remaining
C purchased 1 ticket, 0 remaining
tickets are sold out

总结

  1. 延迟初始化, 如果有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时使用代理模式(类似单例模式,但单例模式强调的是单实例)
  2. 访问控制(保护代理),如果你只希望特定客户端使用服务对象,这里的对象可以是操作系统中非常重要的部分,而客户端则是各种已启动的程序(包括恶意程序),此时可使用代理模式

参考链接

  1. https://lailin.xyz/post/factory.html
  2. https://refactoringguru.cn/design-patterns/proxy
  3. https://learnku.com/articles/33707