🌟 形象比喻:明星与经纪人
想象一个当红明星(真实对象)和她的经纪人(代理对象):
-
粉丝(客户端)想见明星,必须通过经纪人安排
-
经纪人可以控制访问(比如拒绝狗仔队)
-
可以预处理请求(比如先收钱再安排见面)
-
可以延迟创建明星对象(明星太忙,等真正需要时才联系)
-
可以附加服务(见面会前后安排安保和采访)
🏻 核心角色三件套
角色 | 现实对应 | 作用 |
---|---|---|
Subject | 明星的公共合同 | 定义明星和经纪人都要遵守的规范(比如都要有"安排见面"这个方法) |
RealSubject | 明星本人 | 真正提供服务的对象(但粉丝不能直接接触) |
Proxy | 经纪人 | 控制对明星的访问,可以在见面前后添加各种操作(收钱、拍照、安保等) |
🎭 五种经纪人类型
-
远程经纪人(Remote Proxy)
-
就像跨国明星的本地代言人
-
例:RPC调用中的stub(存根)
-
-
虚拟经纪人(Virtual Proxy)
-
"等需要时再请明星出场"
-
例:网页图片的懒加载
-
-
安保经纪人(Protection Proxy)
-
"先检查你的粉丝证"
-
例:Spring Security的权限控制
-
-
智能经纪人(Smart Reference Proxy)
-
"这是今天第100个求签名的,明星该休息了"
-
例:对象引用计数
-
-
缓存经纪人(Cache Proxy)
-
"上次演唱会的录像我这有,不用麻烦明星再唱一遍"
-
例:Redis缓存代理
-
🖼️ 图片加载器案例(生活化版)
java
复制
// 明星接口(什么服务都在这定义) interface Star { void perform(); // 演出方法 } // 真实明星(周杰伦本伦) class RealStar implements Star { public void perform() { System.out.println("周杰伦现场演唱《七里香》..."); } } // 明星经纪人(代理) class StarAgent implements Star { private RealStar star; // 持有明星联系方式 private boolean paid; // 是否付钱 public void takeMoney(int money) { if(money > 1000000) { this.paid = true; System.out.println("收到演出费,安排档期..."); } } @Override public void perform() { if(!paid) { System.out.println("抱歉,请先支付演出费"); return; } // 演出前准备 System.out.println("经纪人:安排场地、安保、宣传..."); // 真正联系明星(延迟加载) if(star == null) { star = new RealStar(); } // 明星演出 star.perform(); // 演出后处理 System.out.println("经纪人:结算费用、处理媒体报道..."); } } // 粉丝(客户端) public class Fan { public static void main(String[] args) { Star fakeJay = new StarAgent(); // 粉丝拿到的是经纪人联系方式 fakeJay.perform(); // 输出:抱歉,请先支付演出费 ((StarAgent)fakeJay).takeMoney(1500000); // 支付费用 fakeJay.perform(); // 真正开始演出流程 } }
💡 模式亮点
✔️ 中介作用:像防火墙一样保护真实对象
✔️ 开闭原则:不修改明星就能新增功能(通过经纪人添加新服务)
✔️ 精细控制:可以实现延迟加载、权限控制等
⚠️ 注意事项
-
不要变成"过度包装"——代理层太多会导致系统变复杂
-
明星和经纪人接口必须一致(不然粉丝会发现破绽)
-
某些情况可能影响性能(每次调用都要经过经纪人)
🌍 现实世界应用
-
Spring AOP:像无处不在的"业务经纪人"
-
MyBatis的Mapper接口:数据库操作的"代理经纪人"
-
Java RMI:远程对象的"跨国经纪人"
-
Hibernate延迟加载:数据的"按需经纪人"
代理模式就像数字世界的"中间商",在保护核心对象的同时,提供了无限可能的增值服务空间!