元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
设计原则
单一职责原则
开闭原则
里氏替换原则
依赖倒置原则
接口隔离原则
迪米特法则
▶
创建型模式
工厂方法模式
抽象工厂
单例模式
建造者模式
原型模式
▶
结构型模式
适配器模式
装饰器模式
代理模式
外观模式
组合模式
桥接模式
享元模式
▶
行为型模式
策略模式
观察者模式
命令模式
模板方法模式
状态模式
责任链模式
迭代器模式
中介者模式
访问者模式
备忘录模式
解释器模式
发布时间:
2025-03-21 15:22
↑
☰
# 代理模式 ## 概述 代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一个代理对象来控制对其他对象的访问。代理对象在客户端和目标对象之间起到中介的作用,可以在不改变目标对象的情况下添加额外的功能。 ## 问题场景 在软件开发中,我们经常会遇到以下场景: 1. 需要控制对对象的访问 2. 需要在访问对象时添加额外的处理 3. 需要延迟加载对象以提高性能 ## 解决方案 代理模式通过创建一个代理类,该类实现与目标对象相同的接口: ```mermaid classDiagram class Subject { <<interface>> +request() } class RealSubject { +request() } class Proxy { -realSubject +request() } Subject <|.. RealSubject Subject <|.. Proxy Proxy o-- RealSubject ``` 主要角色: 1. 抽象主题(Subject): 定义RealSubject和Proxy的共同接口 2. 真实主题(RealSubject): 定义Proxy所代表的真实实体 3. 代理(Proxy): 保存一个引用使得代理可以访问实体 ## 代码示例 ### 1. 基本实现 ```go // Subject 定义抽象主题接口 type Subject interface { Request() string } // RealSubject 定义真实主题 type RealSubject struct{} func (s *RealSubject) Request() string { return "RealSubject handles request" } // Proxy 定义代理类 type Proxy struct { realSubject *RealSubject } func NewProxy() *Proxy { return &Proxy{} } func (p *Proxy) Request() string { // 在调用真实对象之前的处理 if p.realSubject == nil { p.realSubject = &RealSubject{} } // 调用真实对象 result := p.realSubject.Request() // 在调用真实对象之后的处理 return "Proxy: " + result } ``` ### 2. 实际应用示例 ```go // 以图片加载为例 // Image 定义图片接口 type Image interface { Display() } // RealImage 定义真实图片 type RealImage struct { filename string } func NewRealImage(filename string) *RealImage { image := &RealImage{filename: filename} image.loadFromDisk() return image } func (r *RealImage) loadFromDisk() { fmt.Printf("Loading %s from disk\n", r.filename) } func (r *RealImage) Display() { fmt.Printf("Displaying %s\n", r.filename) } // ProxyImage 定义代理图片 type ProxyImage struct { realImage *RealImage filename string } func NewProxyImage(filename string) Image { return &ProxyImage{filename: filename} } func (p *ProxyImage) Display() { if p.realImage == nil { p.realImage = NewRealImage(p.filename) } p.realImage.Display() } // 使用示例 func main() { image := NewProxyImage("test.jpg") // 图片将从磁盘加载 image.Display() // 图片不需要重新加载 image.Display() } ``` ## 适用场景 1. 远程代理 - 为远程对象提供本地代表 - 隐藏对象存在于不同地址空间的事实 2. 虚拟代理 - 延迟加载大型对象 - 优化系统性能 3. 保护代理 - 控制对原始对象的访问 - 用于对象应该有不同访问权限的情况 ## 优缺点 ### 优点 1. 职责清晰 - 真实主题就是实现实际的业务逻辑 - 代理主题负责对真实主题的控制 2. 高扩展性 - 可以在不修改目标对象的前提下扩展功能 - 符合开闭原则 3. 智能化 - 可以实现延迟加载 - 可以对请求进行智能路由和处理 ### 缺点 1. 系统复杂度增加 - 需要额外的代理类 - 可能产生很多代理类 2. 请求处理速度可能降低 - 代理模式会在客户端和真实主题之间加一层中介 - 可能会导致请求的处理速度变慢 ## 实现要点 1. 接口设计 - 代理类和真实主题需要实现相同的接口 - 接口要保持简单明确 2. 代理类型选择 - 远程代理 - 虚拟代理 - 保护代理 - 根据需求选择合适的类型 3. 性能考虑 - 合理使用延迟加载 - 避免过多的代理层次 ## 相关模式 1. 装饰器模式 - 装饰器模式为对象添加行为 - 代理模式控制对象的访问 2. 适配器模式 - 适配器模式改变接口 - 代理模式保持接口不变 3. 外观模式 - 外观模式提供统一的接口 - 代理模式控制对象的访问 ## 总结 代理模式是一种常用的结构型设计模式,它通过代理对象来控制对其他对象的访问。在实际开发中,当需要对对象的访问进行控制或者需要在访问对象时添加额外的处理时,可以考虑使用代理模式。代理模式的核心价值在于: 1. 控制性 - 可以控制对对象的访问 - 可以添加访问控制逻辑 2. 扩展性 - 不修改原有代码 - 符合开闭原则 3. 智能性 - 支持延迟加载 - 可以添加智能处理 在使用代理模式时,需要注意控制代理类的数量和层次,避免系统变得过于复杂。同时,要根据实际需求选择合适的代理类型,确保系统的性能和可维护性。