简介
代理模式(Proxy Pattern)是一种结构型设计模式,用一个类来代理另一个类或几个类的功能。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
延迟初始化(虚拟代理)。如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可使用代理模式。
访问控制(保护代理)。如果你只希望特定客户端使用服务对象,这里的对象可以是操作系统中非常重要的部分,而客户端则是各种已启动的程序 (包括恶意程序), 此时可使用代理模式。
作用
- 为其他对象提供一种代理访问的方式。
- 避免直接访问可能带来的问题,通过接口和代理来实现高扩展。
实现步骤
- 定义一个基础接口,约定一些方法。
- 建立原始类,实现接口方法。
- 再建立代理类,也实现基础接口。代理类调用原始类来实现功能。
UML
Java代码
代理接口类
| |
| public interface Image { |
| void display(); |
| } |
功能代理类
| |
| public class ProxyImage implements Image { |
| |
| private RealImage realImage; |
| private String fileName; |
| |
| public ProxyImage(String fileName) { |
| this.fileName = fileName; |
| } |
| |
| @Override |
| public void display() { |
| System.out.println("ProxyImage::display() " + fileName); |
| if (realImage == null) { |
| realImage = new RealImage(fileName); |
| } |
| |
| realImage.display(); |
| } |
| } |
真实功能类
| |
| public class RealImage implements Image { |
| |
| private String fileName; |
| |
| public RealImage(String fileName) { |
| |
| this.fileName = fileName; |
| loadFromDisk(fileName); |
| } |
| |
| @Override |
| public void display() { |
| System.out.println("RealImage::display() " + fileName); |
| } |
| |
| |
| private void loadFromDisk(String fileName) { |
| System.out.println("RealImage::loadFromDisk() " + fileName); |
| } |
| } |
测试调用
| |
| |
| |
| |
| |
| |
| |
| Image image = new ProxyImage("001.jpg"); |
| |
| |
| image.display(); |
| |
| |
| image.display(); |
Go代码
代理接口类
| |
| type Image interface { |
| Init(fileName string) |
| Display() |
| } |
| |
功能代理类
| |
| type ProxyImage struct { |
| fileName string |
| |
| |
| |
| realImage Image |
| } |
| |
| |
| func (p *ProxyImage) SetFileName(fileName string) { |
| p.fileName = fileName |
| } |
| |
| func (p *ProxyImage) Display() { |
| fmt.Println("ProxyImage::Display() " + p.fileName) |
| if p.realImage == nil { |
| p.realImage = &RealImage{} |
| p.realImage.Init(p.fileName) |
| } |
| |
| p.realImage.Display() |
| } |
| |
真实功能类
| |
| type RealImage struct { |
| fileName string |
| } |
| |
| |
| func (r *RealImage) Init(fileName string) { |
| r.fileName = fileName |
| r.LoadFromDisk(fileName) |
| } |
| |
| func (r *RealImage) Display() { |
| fmt.Println("RealImage::Display() " + r.fileName) |
| } |
| |
| |
| func (r *RealImage) LoadFromDisk(fileName string) { |
| fmt.Println("RealImage::LoadFromDisk() " + fileName) |
| } |
测试调用
| func main() { |
| fmt.Println("test start:") |
| |
| |
| |
| |
| |
| |
| |
| var image = &src.ProxyImage{} |
| image.SetFileName("001.jpg") |
| |
| |
| image.Display() |
| |
| |
| image.Display() |
| } |
C代码简版
| |
| #include <stdio.h> |
| |
| |
| |
| |
| typedef struct Interface |
| { |
| void (*method)(struct Interface *interface); |
| } Interface; |
| |
| |
| typedef struct Concrete |
| { |
| void (*method)(struct Concrete *interface); |
| } Concrete; |
| |
| void real_method(struct Concrete *interface) |
| { |
| printf("调用真实方法 real_method.\n"); |
| } |
| |
| |
| typedef struct Proxy |
| { |
| struct Interface *real_subject; |
| } Proxy; |
| |
| |
| void proxy_method(struct Interface *interface) |
| { |
| struct Proxy *p = (struct Proxy *)interface; |
| p->real_subject->method((struct Interface *)p); |
| } |
| |
| int main() |
| { |
| |
| struct Concrete real_subject = { |
| .method = &real_method, |
| }; |
| |
| |
| struct Proxy proxy_instance = { |
| .real_subject = (struct Interface *)&real_subject, |
| }; |
| |
| |
| struct Interface proxy_interface = { |
| .method = &proxy_method, |
| }; |
| |
| |
| proxy_interface.method((struct Interface *)&proxy_instance); |
| |
| return 0; |
| } |
| |
更多语言版本
不同语言实现设计模式:https://github.com/microwind/design-pattern
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南