结构型模式:代理模式什么是代理模式? 代理模式很像我们生活中的“中间人”。想象一下,当你请明星参加活动时,你通常不会直接

发布时间:2025-06-23 14:14

什么是代理模式?

代理模式很像我们生活中的"中间人"。想象一下,当你请明星参加活动时,你通常不会直接联系明星本人,而是联系他的经纪人。这个经纪人就是一个"代理",他代表明星处理各种事务,筛选请求,安排日程等。

在编程中,代理模式也是这样工作的:我们创建一个"代理对象",它控制着对另一个"真实对象"的访问。当你想使用真实对象时,你实际上是在和代理对象打交道。

为什么要用代理模式?

思考场景:

你想在访问某个重要文件前检查使用者的权限 你需要延迟加载一个很大的图片,直到真正需要显示它时 你希望记录每次对数据库的访问操作 你要在网络上远程调用另一台计算机上的程序

这些场景都很适合使用代理模式,它可以帮我们:

控制访问:像保安一样,检查谁能访问对象 延迟加载:懒惰一点,等真正需要时才创建开销大的对象 增加功能:在不改变原对象的情况下,添加新功能 远程访问:让远程对象看起来就像本地对象一样易用

代理模式长什么样?

用一个餐厅点餐的例子来说明。顾客(客户端)不直接告诉厨师(真实对象)做什么菜,而是告诉服务员(代理),服务员再把请求传给厨师。

// 菜单接口 interface FoodService { void orderFood(String food); } // 厨师(真实对象) class Chef implements FoodService { @Override public void orderFood(String food) { System.out.println("厨师正在烹饪: " + food); } } // 服务员(代理对象) class Waiter implements FoodService { private Chef chef = new Chef(); @Override public void orderFood(String food) { System.out.println("服务员记录订单: " + food); // 检查库存 if ("鱼翅".equals(food)) { System.out.println("抱歉,鱼翅已售罄"); return; } // 转发给厨师 chef.orderFood(food); System.out.println("服务员准备上菜: " + food); } } // 顾客使用 class Customer { public static void main(String[] args) { FoodService waiter = new Waiter(); waiter.orderFood("宫保鸡丁"); waiter.orderFood("鱼翅"); } }

在这个例子中,Waiter(服务员)就是一个代理,它实现了和Chef(厨师)相同的接口,但在转发请求前后添加了额外的处理。

代理模式有哪些种类?

1. 静态代理:写死在代码里的代理

上面餐厅的例子就是静态代理。代理关系在写代码时就确定了,服务员只能代理厨师。

生活例子:固定的售票窗口只能卖特定线路的车票。

2. 动态代理:灵活多变的代理

不用事先为每个对象写好代理类,而是在程序运行时动态创建代理。

生活例子:万能中介,今天代理房屋出租,明天代理二手车买卖。

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 动态代理处理器 class DynamicProxyHandler implements InvocationHandler { private Object target; // 可以是任何对象 public DynamicProxyHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始处理: " + method.getName()); // 调用目标对象的方法 Object result = method.invoke(target, args); System.out.println("处理完成: " + method.getName()); return result; } } // 动态代理示例 public class DynamicProxyDemo { public static void main(String[] args) { // 创建真实对象 Chef chef = new Chef(); // 创建动态代理 FoodService proxy = (FoodService) Proxy.newProxyInstance( FoodService.class.getClassLoader(), new Class<?>[] { FoodService.class }, new DynamicProxyHandler(chef) ); // 使用代理 proxy.orderFood("糖醋排骨"); } }

3. 远程代理:远在天边,近在眼前

让远程对象看起来像本地对象一样。

生活例子:你在国内用支付宝付款,但实际上商品在美国,支付宝作为代理处理了跨国支付细节。

4. 保护代理:守门员

控制对敏感对象的访问。

生活例子:保安检查你的门禁卡,确认你有权限才让你进入大楼。

5. 虚拟代理:按需加载

延迟创建开销大的对象,直到真正需要。

生活例子:你打开网页时,图片可能显示一个占位符,然后慢慢加载出来。

class HeavyImage implements Image { private String filename; public HeavyImage(String filename) { this.filename = filename; loadFromDisk(); } private void loadFromDisk() { System.out.println("加载大图片: " + filename + "(这很慢)"); // 模拟耗时操作 try { Thread.sleep(1000); } catch (InterruptedException e) { } } public void display() { System.out.println("显示: " + filename); } } class ImageProxy implements Image { private String filename; private HeavyImage realImage; public ImageProxy(String filename) { this.filename = filename; } public void display() { // 延迟加载,直到真正需要显示时 if (realImage == null) { realImage = new HeavyImage(filename); } realImage.display(); } }

实际生活中的代理模式

明星和经纪人

明星:真实对象 经纪人:代理 粉丝/商家:客户端

经纪人负责筛选邀约、谈判报酬、安排日程,保护明星不被骚扰。

网购和电商平台

生产厂家:真实对象 电商平台:代理 消费者:客户端

淘宝、京东等平台作为代理,负责展示商品、处理支付、物流等。

法律代理

法律:真实对象 律师:代理 当事人:客户端

律师代表当事人处理法律事务,提供专业建议和服务。

实用场景示例:图片加载器

假设我们在开发一个相册应用,需要显示大量高清图片。如果一次性加载所有图片,会很慢且浪费内存。我们可以使用代理模式来延迟加载图片:

interface Image { void display(); } // 真实图片(重量级对象) class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename = filename; loadFromDisk(); } private void loadFromDisk() { System.out.println("加载图片:" + filename); // 模拟耗时的加载过程 try { Thread.sleep(1000); } catch (InterruptedException e) { } } @Override public void display() { System.out.println("显示图片:" + filename); } } // 图片代理 class ProxyImage implements Image { private String filename; private RealImage realImage; public ProxyImage(String filename) { this.filename = filename; } @Override public void display() { if (realImage == null) { realImage = new RealImage(filename); } realImage.display(); } } // 相册应用 public class PhotoAlbum { public static void main(String[] args) { // 创建相册(使用代理) Image[] album = new Image[5]; album[0] = new ProxyImage("高清风景1.jpg"); album[1] = new ProxyImage("高清风景2.jpg"); album[2] = new ProxyImage("高清风景3.jpg"); album[3] = new ProxyImage("高清风景4.jpg"); album[4] = new ProxyImage("高清风景5.jpg"); // 浏览相册(只有查看的图片才会被加载) System.out.println("打开相册..."); // 用户只查看了第3张图片 album[2].display(); } }

实用场景示例:权限控制

假设我们有一个文件系统,不同用户有不同的访问权限:

// 文件接口 interface File { String read(); void write(String content); } // 真实文件 class RealFile implements File { private String name; private String content; public RealFile(String name) { this.name = name; this.content = "这是" + name + "的内容"; } @Override public String read() { System.out.println("读取文件: " + name); return content; } @Override public void write(String content) { System.out.println("写入文件: " + name); this.content = content; } } // 文件访问代理 class FileAccessProxy implements File { private RealFile realFile; private String user; public FileAccessProxy(String filename, String user) { this.realFile = new RealFile(filename); this.user = user; } @Override public String read() { // 所有用户都可以读取 return realFile.read(); } @Override public void write(String content) { // 检查写入权限 if ("admin".equals(user)) { realFile.write(content); } else { System.out.println("权限不足:用户 " + user + " 没有写入权限"); } } } // 文件系统 public class FileSystem { public static void main(String[] args) { // 普通用户访问 File userFile = new FileAccessProxy("用户数据.txt", "张三"); System.out.println(userFile.read()); // 允许读取 userFile.write("尝试修改内容"); // 拒绝写入 System.out.println(); // 管理员访问 File adminFile = new FileAccessProxy("用户数据.txt", "admin"); System.out.println(adminFile.read()); // 允许读取 adminFile.write("管理员修改的内容"); // 允许写入 } }

代理模式的优点

单一职责:真实对象专注核心功能,代理对象负责控制逻辑 扩展性好:不改变原对象,就能在外部添加功能 保护真实对象:限制对真实对象的直接访问 降低系统耦合度:客户端和真实对象不直接交互

代理模式的缺点

增加复杂度:新增了代理类,系统更复杂 可能降低性能:因为多了一层调用,特别是动态代理 可能引入不透明性:客户端不知道是在和代理打交道还是真实对象

代理模式和其他模式的区别

代理模式 vs 装饰器模式

代理模式:控制对象访问 装饰器模式:扩展对象功能

区别在于意图:门卫(代理)决定是否让你进入,而化妆师(装饰器)则是让你看起来更漂亮。

代理模式 vs 适配器模式

代理模式:接口相同,加入控制 适配器模式:转换不兼容的接口

区别在于:翻译(适配器)帮你和说不同语言的人交流,而律师(代理)则是以你的名义和法官交流。

什么时候用代理模式?

当你遇到这些情况时,考虑使用代理模式:

需要控制对某个对象的访问 需要在不修改已有代码的情况下添加功能 对象创建成本高,需要延迟初始化 需要在远程操作中隐藏复杂性 需要统一处理对多个对象的访问(如缓存、日志)

如何在实际项目中应用代理模式?

确定真实对象:明确需要被代理的对象 设计公共接口:代理和真实对象需要实现相同的接口 实现代理类:基于需求添加额外功能 选择代理类型:静态代理简单直接,动态代理更灵活 考虑性能影响:避免在性能关键路径上使用过于复杂的代理

总结

代理模式就像生活中的"中间人",它站在客户和真实对象之间,控制和扩展对真实对象的访问。无论是权限控制、延迟加载,还是增加额外功能,代理模式都能优雅地解决这些问题。

关键是理解代理模式的核心思想:通过引入一个新的对象来控制对原对象的访问。一旦掌握了这个思想,你就能在各种情景中灵活运用代理模式,让你的代码更加健壮和易于扩展。

网址:结构型模式:代理模式什么是代理模式? 代理模式很像我们生活中的“中间人”。想象一下,当你请明星参加活动时,你通常不会直接 https://mxgxt.com/news/view/1501319

相关内容

结构型模式:代理模式什么是代理模式? 代理模式很像我们生活中的“中间人”。想象一下,当你请明星参加活动时,你通常不会直接
Java设计模式之代理模式——经纪人的工作
IDOL的代理模式
代理模式
“共享明星”,你想不到的代言最佳模式
“艺人商务代理经纪”模式的突围与逆袭
数据库中的关系模式是指什么模式
《我想和你唱》“星素互动”新模式
用户画像模型,构建用户画像模型的方式
原员工揭张庭夫妇传销模式:代理买货可加老板微信,骗别人加盟

随便看看