一、从剧情中思考代理模式
Tony周末正在公司苦命的加班,这时候快递小哥打来电话,李力买的雪地靴送到了。这时候李力想到合租的Wendy今天休息,就让Wendy代他收一下快递。
用代码来模仿剧情
package main
import "fmt"
type ReceiveParcel interface {
GetName() string
Receive(parcelContent string)
}
type TonyReception struct {
Name string
PhoneNum string
}
func (t *TonyReception)GetName() string{
return t.Name
}
func (t *TonyReception)GetPhoneNum() string{
return t.PhoneNum
}
func (t *TonyReception)Receive(parcelContent string){
fmt.Printf("货物主人:%s,手机号:%s\n",t.GetName(),t.GetPhoneNum())
fmt.Printf("接收到一个包裹,包裹内容为:%s\n",parcelContent)
}
type WendyReception struct {
Name string
Receiver ReceiveParcel
}
func (w *WendyReception)GetName() string{
return w.Name
}
func (w *WendyReception)Receive(parcelContent string) {
fmt.Printf("我是%s的朋友,我来帮他代收快递!\n",w.Receiver.GetName())
if w.Receiver != nil{
w.Receiver.Receive(parcelContent)
}
fmt.Printf("代收人:%s",w.GetName())
}
func testReceiveParcel(){
tony := &TonyReception{Name: "Tony",PhoneNum: "18512345678"}
fmt.Println("Tony 接收:")
tony.Receive("雪地靴")
fmt.Println()
fmt.Println("wendy代收:")
wendy := &WendyReception{Name: "Wendy",Receiver: tony}
wendy.Receive("雪地靴")
}
func main() {
testReceiveParcel()
}
输出结果:
Tony 接收:
货物主人:Tony,手机号:18512345678
接收到一个包裹,包裹内容为:雪地靴
wendy代收:
我是Tony的朋友,我来帮他代收快递!
货物主人:Tony,手机号:18512345678
接收到一个包裹,包裹内容为:雪地靴
代收人:Wendy
Process finished with exit code 0
二、从剧情中思考代理模式
2.1 什么是代理模式
为其他对象提供一种代理以控制对这个对象的访问。故事中Wendy使用Tony的手机号获得快递员的验证才能成功接收快递。像这样,一个对象完成某项任务或者任务,是通过对另外一个对象的引用来完成,这种模式叫代理模式。
2.2 代理模式的设计思想
代理模式的英文叫作Proxy或Surrogate,其核心思想是:
● 使用一个额外的间接层来支持分散的、可控的、智能的访问。
● 增加一个包装和委托来保护真实的组件,以避免过度复杂。
代理对象可以在客户端和目标对象之间起到中间调和的作用,并且可以通过代理对象隐藏不希望被客户端看到的内容和服务,或者添加客户需要的额外服务。
三、代理模式的模型抽象
3.1 类图
Subject 是活动主题的抽象基类,负责定义统一的接口,如故事剧情中的 ReceiveParcel。RealSubject是真实主题,即Subject的具体实现类,如故事剧情中的TonyReception。ProxySubject是代理主题,代理RealSubject的功能,如故事剧情中的WendyReception。
3.2模型说明
3.2.1.设计要点
代理模式中主要有三个角色,在设计代理模式时要找到并区分这些角色。
(1)主题(Subject):定义操作、活动、任务的接口类。
(2)真实主题(RealSubject):真正完成操作、活动、任务的具体类。
(3)代理主题(ProxySubject):代替真实主题完成操作、活动、任务的代理类。
3.2.2.代理模式的优缺点
优点:
(1)代理模式能够协调调用者和被调用者,在一定程度上降低系统的耦合度。
(2)可以灵活地隐藏被代理对象的部分功能和服务,也可以增加额外的功能和服务。
缺点:
(1)由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
(2)实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
四、应用场景
(1)不想或者不能直接引用一个对象时,如在移动端加载网页信息时,因为下载真实大图比较耗费流量、影响性能,可以用一个小图代替进行渲染(用一个代理对象去下载小图),在真正点击图片时,才下载大图,显示大图效果。还有HTML中的占位符,其实也是代理模式的思想。
(2)想对一个对象的功能进行加强时,如在字体(Font)渲染时,对粗体(BoldFont)进行渲染时,可使用字体Font对象进行代理,只要在对Font进行渲染后进行加粗的操作即可。
(3)各种特殊用途的代理:远程代理、虚拟代理、Copy-on-Write 代理、保护(Protect or Access)代理、Cache代理、防火墙(Firewall)代理、同步化(Synchronization)代理、智能引用(Smart Reference)代理。
摘录来自
人人都懂设计模式:从生活中领悟设计模式:Python实现