持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
代理模式
代理模式是一种代理模式是一种结构模式,其目的是提供对象的代理或中介来控制其访问。 通常包装一个对象来隐藏它的一些特性。
首先,从一个简单的代码先入手理解代理模式:
type Drive interface{
Drive()
}
type Car struct{}
func (c *Car) Drive(){
fmt.Println("Car driven")
}
type Driver struct{
Name string
}
type CarProxy struct {
car Car
driver *Driver
}
func (c *CarProxy) Drive(){
fmt.Println("Car driver name "+c.driver.Name)
}
func NewCarProxy(driver *Driver) *CarProxy {
return &CarProxy{Car{},driver}
}
实现一个代理类,代理类返回真正的实体。访问代理对象其实就是通过代理对象访问目标。这样就必须要求代理类实现和目标类相同的方法。这样外部就可以通过控制代理类就能完全的控制目标类。
当然代理类也可以继续扩展一些目标类没有的方法,增加额外的功能。
func main(){
car := NewCarProxy(&Driver{"司机"})
car.Drive()
}
这里又使用工厂模式,返回一个代理类对象。然后就可以通过代理类操作目标对象。可以看到代理类中的 Driver() 方法中使用的就是 c.driver.name .因为 Car 对象是作为代理类的一个属性存在。
多增加一个目标类,可以更好的体现出代理类的功能:
type Bus struct{}
type CarProxy struct {
car Car
bus Bus
driver *Driver
}
func NewDriveProxy(type string) {
if type == "car" {
return &CarProxy{Car{},driver}
} else if type == "bus" {
return &CarProxy{Bus{},driver}
}
}
这样就可以更清晰的看到代理类的作用,根据不同的类型访问不同的目标对象。对于调用者无需关注底层的实现。
优点和缺点
优点
- 调用者无需关注目标对象,仅有代理类去控制目标对象
- 允许调用者不关注目标对象的声明周期
- 即便目标对象没有设计好或不可用,代理类都会保持工作
- 符合开闭设计原则
缺点
- 代理对象和目标对象需要实现相同的接口和方法,多个目标对象的话就会导致有很多的代理类
- 一旦目标类修改就会影响代理类,“牵一发而动全身”的不好现象
- 服务响应可能会受到影响,因为会增加执行时间的延迟。
适用场景
代理模式适合用在一些非功能的需求上,比如监控,日志,鉴权等,通过使用代理模式,将业务功能和其非功能的进行解耦。由代理类统一处理。