代码界的「明星经纪人」:代理模式的替身艺术
一、当访问开始「层层把关」
你是否经历过这样的场景?
想见明星却被经纪人拦住:「先填申请表,排队等通知」;
访问国外网站时,VPN默默替你转发请求;
网购付款时,支付宝作为中间人保护你的银行卡信息...
代理模式就像代码界的「职业替身」------「别直接上!让我先验明正身,过滤危险,必要时再召唤本体!」 通过中间人控制访问,让敏感操作穿上防弹衣。
二、经纪人的工作手册(UML图)
java
┌─────────────┐ ┌─────────────┐
│ Client │ │ Subject │
└──────┬──────┘ ├─────────────┤
│ │ +request() │
┌──────▼──────┐ └──────△──────┘
│ Proxy │ │
├─────────────┤ ┌──────┴──────┐
│ +request() │ │ RealSubject│
└─────────────┘ └─────────────┘
- 粉丝(Client):发起请求的调用方
- 明星接口(Subject):定义服务规范
- 经纪人(Proxy):控制访问的中间层
- 真明星(RealSubject):真正干活的实现类
三、娱乐圈的替身大戏(代码实战)
1. 定义明星标准(接口)
java
// 明星必须会签名和合影
interface Celebrity {
void signAutograph(String fanName);
void takePhoto();
}
2. 顶流明星(真实对象)
java
// 周杰伦本尊(资源宝贵,不能随便见)
class JayChou implements Celebrity {
public void signAutograph(String fanName) {
System.out.println("🎤 给" + fanName + "签名:「哎哟不错哦」");
}
public void takePhoto() {
System.out.println("📸 合影:奶茶三兄弟经典POSE");
}
}
3. 严格经纪人(代理对象)
java
class CelebrityProxy implements Celebrity {
private JayChou realStar;
private Set<String> vipFans = Set.of("方文山", "郎朗", "蔡徐坤");
public void signAutograph(String fanName) {
if (checkAccess(fanName)) {
lazyInit();
realStar.signAutograph(fanName);
} else {
System.out.println("🚫 " + fanName + ":非VIP不得近距离接触");
}
}
public void takePhoto() {
System.out.println("📢 经纪人:合影需额外付费500元");
}
private boolean checkAccess(String fanName) {
return vipFans.contains(fanName);
}
private void lazyInit() {
if (realStar == null) {
System.out.println("⏳ 经纪人:正在联系周董...");
realStar = new JayChou(); // 延迟加载
}
}
}
4. 粉丝见面会
java
public class FanMeeting {
public static void main(String[] args) {
Celebrity proxy = new CelebrityProxy();
// 普通粉丝试图签名
proxy.signAutograph("普通粉丝张三"); // 被经纪人拦截
// VIP粉丝签名
proxy.signAutograph("方文山"); // 触发初始化真明星
proxy.takePhoto(); // 经纪人附加额外规则
}
}
四、替身类型大全(代理家族)
代理类型 | 功能描述 | 现实类比 |
---|---|---|
虚拟代理 | 延迟加载大资源 | 演唱会预售票(先卖票后搭舞台) |
保护代理 | 权限控制 | 公司门禁卡(不同权限进不同区域) |
远程代理 | 处理网络通信细节 | 海外代购(本地对接,跨国发货) |
缓存代理 | 存储重复请求结果 | 快递柜(暂存包裹避免重复配送) |
智能代理 | 记录日志、统计耗时等 | 健身教练(记录训练数据) |
五、代码经纪人的就业现场
- Spring AOP :
@Transactional
注解背后的数据库事务代理 - MyBatis延迟加载:关联对象按需查询
- RPC框架:本地调用远程服务的网络代理
- 图片预加载:先显示缩略图,点击再加载原图
- 权限校验:接口访问前的身份验证拦截器
冷知识 :
Java动态代理可以在运行时生成代理类,连经纪人都能「即插即用」!
六、防替身穿帮指南
- 别让代理变上帝
java
// 错误示范:代理类处理业务逻辑
class BadProxy {
void handleBusiness() { /* 既做访问控制又处理核心业务 */ }
}
- 优先组合替代继承
java
// 通过组合持有目标对象(更灵活)
class Proxy {
private RealSubject target;
// ...
}
- 区分代理与装饰器
text
代理:控制访问(经纪人限制你见明星)
装饰器:增强功能(给明星化妆+打光)
- 动态代理妙用
java
// JDK动态代理示例
Celebrity proxy = (Celebrity) Proxy.newProxyInstance(
ClassLoader.getSystemClassLoader(),
new Class[]{Celebrity.class},
(proxy, method, args) -> {
System.out.println("动态代理拦截:" + method.getName());
return method.invoke(realStar, args);
}
);
- 缓存失效策略
java
// 缓存代理需要设置超时时间
if (cache.isExpired()) {
refreshCache();
}
七、替身行业总结
代理模式让代码成为智能保镖:
- ✅ 要:用于控制访问或增强非功能特性
- ✅ 要:保持代理与目标对象的接口一致性
- ❌ 不要:让代理类承担核心业务逻辑
- ❌ 不要:在简单场景过度设计
当你在Spring中轻松使用@Cacheable
时,请想起代理模式------那个默默为你缓存结果的隐形管家!