12. 代理模式(Proxy)
12. 代理模式(Proxy)
问题:想在访问对象时加一层控制(延迟加载、权限校验、缓存等)。
核心:代理对象和目标对象实现同样接口,代理内部控制对目标的访问。
interface DisplayableImage {
display(): void;
}
class RealImage implements DisplayableImage {
constructor(private filename: string) {
this.loadFromDisk();
}
private loadFromDisk(): void { console.log(`从磁盘加载: ${this.filename}`); }
display(): void { console.log(`显示: ${this.filename}`); }
}
class ProxyImage implements DisplayableImage {
#realImage?: RealImage;
constructor(private filename: string) {}
display(): void {
if (!this.#realImage) {
this.#realImage = new RealImage(this.filename);
}
this.#realImage.display();
}
}
const img = new ProxyImage('photo.jpg');
img.display(); // 从磁盘加载 → 显示(第一次,触发加载)
img.display(); // 显示(第二次,直接用缓存)package proxy
import "fmt"
type Image interface {
Display()
}
type RealImage struct {
filename string
}
func NewRealImage(filename string) *RealImage {
img := &RealImage{filename: filename}
img.loadFromDisk()
return img
}
func (r *RealImage) loadFromDisk() {
fmt.Printf("从磁盘加载: %s\n", r.filename)
}
func (r *RealImage) Display() {
fmt.Printf("显示: %s\n", r.filename)
}
type ProxyImage struct {
filename string
realImage *RealImage
}
func NewProxyImage(filename string) *ProxyImage {
return &ProxyImage{filename: filename}
}
func (p *ProxyImage) Display() {
if p.realImage == nil {
p.realImage = NewRealImage(p.filename)
}
p.realImage.Display()
}实战场景
- 图片懒加载:代理先占位,真正进入视口或被显示时才加载真实图片。
- 权限代理:访问敏感资源前先检查登录状态、角色、租户范围,通过后才调用真实服务。
- 缓存代理:查询接口前先查缓存,未命中再请求真实数据源,并把结果写回缓存。
- 远程代理:本地对象看起来像普通 service,实际调用通过 HTTP、RPC 或消息队列转发到远程服务。
- 虚拟代理:真实对象创建成本很高时,代理延迟初始化,例如大型模型、报表、编辑器实例。
- 日志审计:对关键操作包一层代理,记录调用人、参数摘要、结果和耗时。
- 限流代理:在调用真实接口前检查频率、配额或并发数,超限时直接拒绝。
- 响应式代理:前端框架用代理拦截对象读写,收集依赖并触发更新。
- 安全沙箱:插件或脚本不直接拿到真实对象,而是拿到受限代理,只暴露允许的能力。
- Mock 代理:开发环境代理 API 请求,某些接口返回本地 mock,其他接口转发到真实后端。
ES6 的
Proxy就是语言级别的代理支持。