代理
通过代理控制对目标的访问。
结构型
说明
权限校验、延迟加载等发生在真实对象之前或之后;代理保持相同接口。
分析
Guard 与 Remote 都实现 Data,因此客户端无需因访问控制而更改调用代码。代理先检查 Allowed,只有允许时才转发给真实对象。
Guard 保持 Data.Get 接口,Allowed=false 时直接返回 denied,根本不会调用 Remote.Get。示例用字符串表达拒绝,真实接口应避免把错误字符串与合法业务数据混淆。代理成立的前提是访问必须经过它;若调用方还能直接获取 Remote,权限控制就不是完整边界。
查看图表代码
适用前提与边界
同样的结构可用于缓存或延迟创建,但涉及权限时必须确保不存在绕过代理的直接入口。 只有接口适配或独立变化确实存在时,才增加额外包装层。
示例输入与调用
go
var data Data = Guard{Target: Remote{}, Allowed: false}
fmt.Println(data.Get())运行输出
text
denied完整 Go 示例
go
package main
import "fmt"
type Data interface{ Get() string }
type Remote struct{}
func (Remote) Get() string {
return "secret"
}
type Guard struct {
Target Data
Allowed bool
}
func (g Guard) Get() string {
if !g.Allowed {
return "denied"
}
return g.Target.Get()
}
func main() {
var data Data = Guard{Target: Remote{}, Allowed: false}
fmt.Println(data.Get())
}继续阅读
- 设计意图与对象责任
- 设计意图与对象责任
- 设计意图与对象责任