代理模式的定义其实比较简单:代理模式给某对象提供一个代理对象,由代理对象来控制对原对象的引用。生活中比较常见的代理模式的应用比如:火车票代购、代办保险、UU跑腿、武侠片中的替身、nginx反向代理等等这种类似于中介的模式统统可以归于代理模式。“本人” 和“代理人”都是对象,“ 代理人”可以代替“本人”去完成一些工作,甚至是出色完成( 超期完成)某些工作,这里的“出色完成”就可以理解为对原工作的一种增强实现,这点有点类似于装饰器模式。
那么,为什么会存在代理模式呢?我们知道,存在即合理,很多情况下,客户类不想或不能直接用委托对象,这时候使用代理类充当中介作用,这种情况下代理类和委托类实现相同的接口;另外,有时候我们会想增强委托类,这个时候使用代理类来完成也是再合适不过了,也是符合开闭原则(对拓展开放,对修改关闭)的。
代理模式也叫做委托模式,代理类一般包含被委托类的引用,我们来说下上面三个角色的定义:
- 抽象主题角色( Subject) :抽象主题角色往往是一个抽象类或接口,用来定义被委托类也就是真实的业务处理类和代理类的一些通用操作 ;
- 具体的主题角色( RealSubject) :该类实现Subject,是真实被委托的类,也是具体业务逻辑的真正执行者;
- 代理类或委托类(Proxy) :该类同样实现Subject,在客户类和本地之间充当中介作用,将客户端的业务操作委托给RealSubject执行,并在执行前后做一些预处理或者善后工作。 有点类似于AOP,实际上AOP使用的也是代理模式,不过是动态代理。
import "fmt"
type IBuyer interface {
Login(username,password string)
BuyTicket()
}
type BuyerProxy struct {
b *Buyer
}
func (b *BuyerProxy)Login(username,password string) {
b.b.Login(username,password)
}
func (b *BuyerProxy)BuyTicket() {
before()
b.b.BuyTicket()
after()
}
func before() {
fmt.Println("准备定时任务,开始刷票")
}
func after() {
fmt.Println("刷票成功,短信通知用户")
}
type Buyer struct {
name string
}
func (b *Buyer)Login(username,password string) {
fmt.Println(b.name,"使用",username,"登陆成功")
}
func (b *Buyer)BuyTicket() {
fmt.Println(b.name,"购票成功")
}
buyer := &Buyer{name: "123"}
proxy := BuyerProxy{b: buyer}
proxy.Login("678","345")
proxy.BuyTicket()
123 使用 678 登陆成功
准备定时任务,开始刷票
123 购票成功
刷票成功,短信通知用户
--- PASS: TestBuyer_BuyTicket (0.00s)