从经纪人到代码替身,一文读懂代理模式的奥秘

87 阅读8分钟

面向对象设计模式 —— 代理模式详解​

{"type":"load_by_key","id":"","key":"banner_image_0","width":0,"height":0,"image_type":"search","pages_id":"5078216761112322","genre":"技术文章","artifact_key":5077640332496386}

🤖在面向对象编程的浩瀚宇宙中,设计模式就像是开发者手中的神奇魔杖,轻轻一挥,就能将复杂的问题变得清晰明了!而代理模式(Proxy Pattern),作为结构型设计模式里一颗闪耀的星星✨,凭借独特的代理机制,在各种场景中大显身手。今天,就让我们一起揭开它神秘的面纱吧!​

一、代理模式的概念与核心思想​

代理模式的核心,简单来说就是请了一个 “替身” 来帮忙处理事情🧍。这个 “替身” 就是代理对象,它站在客户端和真实对象之间,充当着沟通的桥梁。当客户端想要和真实对象 “打交道” 时,不再直接接触,而是通过代理对象来传递请求。

代理对象手里握着真实对象的 “联系方式”(引用),它可不是个 “摆设” 哦😎!在把请求交给真实对象处理前后,代理对象会执行一系列额外操作,比如严格的权限验证、高效的缓存处理,甚至是复杂的远程调用,从而实现对真实对象的 “贴心保护” 和功能拓展。​

举个超形象的生活例子🌍:大明星身边总有一位忙碌的经纪人。粉丝们想要和明星见面、合作,都得先通过经纪人安排。经纪人会对各种请求进行筛选、协调,处理各种琐碎事务,而明星只要专注于舞台表演就好。这里,经纪人就是代理对象,明星是真实对象,粉丝就是客户端啦!​

二、代理模式的结构与角色​

代理模式主要由以下几个重要角色组成🎭:​

  1. 抽象主题(Subject):它就像是一个 “统一标准”📄,定义了真实主题和代理主题都必须遵守的规则(也就是接口)。有了它,客户端就能用同样的方式和真实对象、代理对象交流,超级方便!​
  1. 真实主题(Real Subject):这可是真正的 “干活小能手”💪!它实现了抽象主题规定的接口,实实在在地处理各种业务逻辑,所有关键操作都在这里完成。​
  1. 代理主题(Proxy):作为 “中间协调员”🤝,它同样实现了抽象主题接口,还牢牢 “抓住” 真实主题的引用。在客户端发出请求时,代理主题会先执行检查权限、记录日志等额外操作,然后再把请求 “转手” 给真实主题。​

再用租房的例子来说明🏠:抽象主题就好比 “租房服务” 接口,里面规定了查看房源、签订合同等方法;真实主题是 “房东”,负责房屋出租的实际业务;代理主题则是 “房屋中介”,中介会在租客看房前仔细核实身份,签合同时帮忙处理各种手续,最后把租客的需求传达给房东。​

三、代理模式的实现方式​

代理模式有两种常见的实现方式,就像两种不同的 “魔法技能”🪄,各有千秋~​

(一)静态代理​

静态代理是在编译期就把代理类 “固定” 下来🧱,代理类和真实类实现相同的接口,代理类里还 “藏” 着一个真实类的引用。来看一段 Java 代码示例👇:​


取消自动换行复制

// 抽象主题接口,就像租房服务的“标准合同”​

interface Rent {​

void rent(); // 定义租房方法​

}​

​

// 真实主题类,房东本尊登场!​

class Landlord implements Rent {​

@Overridepublic void rent() {​

System.out.println("房东出租房屋");​

}​

}​

​

// 代理主题类,房屋中介闪亮登场✨​

class HouseAgent implements Rent {​

private Landlord landlord; // 握着房东的“联系方式”​public HouseAgent(Landlord landlord) {​

this.landlord = landlord;​

}​

​

@Overridepublic void rent() {​

System.out.println("中介进行租客身份核实");​

landlord.rent(); // 把请求转给房东​

System.out.println("中介协助签订租房合同");​

}​

}​

​

// 客户端测试,租客来租房啦🏠​

public class Main {​

public static void main(String[] args) {​

Landlord landlord = new Landlord();​

HouseAgent agent = new HouseAgent(landlord);​

agent.rent();​

}​

}​

静态代理的优点是简单易懂,就像 “傻瓜相机”📷,拿起来就能用;但缺点也很明显,如果抽象主题的方法很多,代理类的代码就会变得又长又复杂,而且每增加一个真实类,都得手动创建对应的代理类,维护起来超麻烦😣!​

(二)动态代理​

动态代理就像拥有 “七十二变” 的能力🧞,能在运行时动态生成代理类,不需要提前在编译期定义。Java 中利用 java.lang.reflect.Proxy 类和 InvocationHandler 接口来施展这个 “魔法”。看代码~​


import java.lang.reflect.InvocationHandler;​

import java.lang.reflect.Method;​

import java.lang.reflect.Proxy;​

​

// 抽象主题接口,还是那个“租房服务合同”​

interface Rent {​

void rent();​

}​

​

// 真实主题类,房东依旧在~​

class Landlord implements Rent {​

@Overridepublic void rent() {​

System.out.println("房东出租房屋");​

}​

}​

​

// 调用处理器,相当于“魔法咒语”的执行者🧙​

class ProxyHandler implements InvocationHandler {​

private Object target; // 目标对象,也就是真实对象​public ProxyHandler(Object target) {​

this.target = target;​

}​

​

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {​

System.out.println("动态代理进行前置处理");​

Object result = method.invoke(target, args);​

System.out.println("动态代理进行后置处理");​

return result;​

}​

}​

​

// 客户端测试,租客再次出动!​

public class Main {​

public static void main(String[] args) {​

Landlord landlord = new Landlord();​

ProxyHandler handler = new ProxyHandler(landlord);​

Rent proxy = (Rent) Proxy.newProxyInstance(​

landlord.getClass().getClassLoader(),​

landlord.getClass().getInterfaces(),​

handler​

);​

proxy.rent();​

}​

}​

在动态代理里,ProxyHandler 实现了 InvocationHandler 接口,重写的 invoke 方法就是 “魔法核心”🔮,在调用真实对象方法前后执行额外逻辑。通过 Proxy.newProxyInstance 方法就能动态生成代理对象。它的优点是灵活多变,能大大减少重复代码;不过缺点是理解和调试起来有点难度,像是解开一团复杂的毛线🧶~​

四、代理模式的应用场景​

代理模式在实际开发中有超多实用场景,简直是 “万能小帮手”🔧!​

(一)远程代理​

当客户端想要访问远在 “千里之外” 的远程对象时🚀,直接访问就像隔着千山万水,困难重重。这时候远程代理闪亮登场✨!客户端可以像访问本地对象一样轻松操作,而代理对象会默默处理网络通信、数据传输等复杂细节。比如在分布式系统中,客户端通过远程代理调用远程服务器上的服务,超方便!​

(二)虚拟代理​

如果创建一个真实对象的 “代价” 很高,或者暂时用不到它,虚拟代理就派上用场啦🤗!它会先 “假装” 自己是真实对象,等客户端真正需要时,再把真实对象 “召唤” 出来,这样就能大大提高系统性能和资源利用率。就像加载图片时,先显示一个小占位符(虚拟代理),等图片加载好了,再展示高清大图~​

(三)保护代理​

保护代理就像一位 “忠诚的保镖”🛡️,专门负责守护真实对象的安全。只有满足特定条件的客户端,才能通过代理对象访问真实对象。比如在系统里,只有拥有特定权限的用户才能查看敏感资源,这时候保护代理就会严格进行权限验证!​

(四)智能引用代理​

智能引用代理就像一个 “贴心小管家”🧑‍🍼,在访问真实对象时,它会记录访问次数等信息,还能在对象不再使用时,自动释放资源。在 Java 的垃圾回收机制中,它就能大显身手,帮忙管理对象的生命周期!​

五、代理模式的优缺点​

(一)优点​

  1. 职责清晰:代理对象和真实对象分工明确,一个负责 “对外交涉” 和处理额外逻辑,一个专注 “内部业务”,代码的可维护性和可读性直线上升📈!​
  1. 扩展性好:想添加新功能?没问题!通过代理对象就能轻松实现,还不用修改真实对象的代码,完全符合开闭原则,就像给房子轻松 “装修” 一样🏠!​
  1. 保护真实对象:有了代理模式,就像给真实对象穿上了一层 “防弹衣”🛡️,能有效防止非法访问,系统安全性大大提高!​

(二)缺点​

  1. 增加系统复杂度:引入代理对象后,系统里的类变多了,对象之间的关系也变得错综复杂,理解和维护起来就像走迷宫🧩,有点头疼~​
  1. 可能影响性能:因为代理对象要在调用真实对象前后执行额外操作,就像多了几道 “关卡”🚪,频繁调用时可能会带来性能开销。​

六、总结​

代理模式真的是面向对象编程里的 “宝藏模式”🎁!通过引入代理对象,实现了对真实对象的巧妙控制和功能增强。无论是静态代理还是动态代理,都有各自的 “用武之地”。在实际开发中,合理运用代理模式,能让代码结构更清晰,系统更易于维护和扩展。而且随着技术不断发展,代理模式在各种框架和技术中都被广泛应用,比如 Spring 框架中的 AOP(面向切面编程)就 “暗藏” 代理模式的身影!深入掌握代理模式,绝对能让开发者的能力 “更上一层楼”🏆!​