设计模式(四)--代理模式
设计模式(四)–代理模式
其他链接
JVM学习笔记(一)
JVM学习笔记(二)
JVM学习笔记(三)
JVM学习笔记(四)
(待更新…)
Java NIO
(待更新…)
设计模式(一)
设计模式(二)
设计模式(三)
设计模式(四)
(待更新…)
代理模式
1.简介
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
代理模式又分以下两种:
-
静态代理
-
动态代理
2.静态代理
角色
- 抽象角色:接口或抽象类,统一操作标准
- 真实角色:被代理的角色(如房东)
- 代理角色:负责代理真实角色,代理真实角色去做其附属操作(如中间商)
- 客户:访问代理的人。(如租客)
代码实现
租房接口—抽象角色
public interface Rent{
//出租房子
public void rent();
}
房东类----真实角色
public class Host implements Rent{
//租房子
public void rent(){
System.out.println("出租房子");
}
}
代理类—代理角色
public class Proxy implements Rent{
private Host host;
public Proxy(){}
public Proxy(Host host){
this.host = host;
}
//代理方法
public void rent(){
//代理角色给真实角色扩展了功能
this.money();
host.rent();
this.seeHouse();
}
//一些代理的附属操作
public void money(){
System.out.println("代理收钱");
}
public void seeHouse(){
System.out.println("代理带你看房子");
}
}
客户类—客户
public class Client{
public static void main(String[] args){
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
好处
1、代理模式能将代理对象与真实被调用的目标对象分离。
2、一定程度上降低了系统的耦合度,扩展性好。
3、可以起到保护目标对象的作用。
4、可以对目标对象的功能增强。
3.动态代理
学动态代理最重要是get到那个动的概念,过于理论是很难理解动态代理的,结合代码实践反而易于理解。动态代理的核心就是通过反射机制实现的,通过反射获得被代理类的方法和调用执行器的方法。
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的
- 动态代理分两大类:
- 基于接口的动态代理
- 基于类的动态代理
代码实现
租房接口—抽象角色
public interface Rent{
//出租房子
public void rent();
}
房东类----真实角色
public class Host implements Rent{
//租房子
public void rent(){
System.out.println("出租房子");
}
}
代理调用执行器
如果按静态代理那套的话 ,这里要写代理角色的,但是动态代理不同,动态代理的代理角色是动态生成的,这也是体现其动的表现。我们通过这个代理执行其去动态生成代理类。
- InvocationHandler是java reflect包下的接口,其提供了invoke方法接口,用于代理角色的方法执行接口。
- Proxy 也是java reflect包下的,其提供了一个静态方法放回一个动态代理类。
如果上面两个没听懂的话,无所谓,只要记住Proxy提供放回一个动态代理角色的方法,而实现InvocationHandler接口的类可以通过invoke()执行代理方法即可。
public class ProxyInvocationHandler implements InvocationHandler{
//被代理的接口
private Object target;
public void setTarget(Object target){
this.target = target;
}
public Object getProxy(){
//返回动态代理类
/*
Proxy的静态方法newProxyInstance返回的是代理对象,参数如下:
(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
loader:实现InvocationHandler接口的类的加载器
interfaces:被代理类的接口
h:实现InvocationHandler的类
*/
return Proxy.newProxyInstance(this.getClass().getClassLoad(),
target.getClass().getInterfaces(),
this)
}
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
/*
动态代理类一旦调用接口方法,就会执行invoke方法,
在这里可以对method.getName()做判断,看看是调用了那个接口方法。
*/
System.out.println("这里可以添加代理操作!!!");
Object result = method.invoke(this.target,args)
return result;
}
}
客户类—客户
public class Client{
public static void main(String[] args){
//创建被代理的类
Host host = new Host();
//创建代理调用执行器
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//设置代理对象
pih.setTarget(host);
//放回动态代理
Rent hostProxy = (Rent)pih.getProxy();
//动态代理调用接口方法
hostProxy.rent();
}
}
解析
上面代码执行流程开始解析:
- 创建被代理的类,这没什么好说的。
- 创建好代理调用执行器,该执行器实现了InvocationHandler接口,并且我还创建了getProxy()方法,使其能放回动态代理类。
- 调用setTarget(host)给该代理调用执行器绑定要被代理的对象
- 调用getProxy()方法,这步就好好好解析了,看看Proxy.newProxyInstance()的参数,这些参数告知了Proxy,被代理类有哪些接口方法(就是实现了那个接口方法interfaces),也告知了Proxy哪些类实现了InvocationHandler接口,并及其类的加载器。这些参数告知了放回了代理类应该有哪些方法,当这些方法被调用时,应该去找那个InvocationHandler接口的实现类去执行。
- 代理类执行rent()接口方法,实践上是去调用了ProxyInvocationHandler中的invoke()方法。
机制解析:
核心:就是通过反射机制获得被代理类的方法和调用执行器的方法。
有人就会问,为什么Proxy放回的动态代理会有被代理类的接口方法?
- 那是因为啊,在newProxyInstance()时,你告知Proxy 被代理类的接口是那个(interfaces参数),所以放回的动态代理是实现了被代理类的接口方法的。
那为什么调用被代理类的接口的方法是去调用了ProxyInvocationHandler的invoke()方法呢?
- 这就是动态代理的精髓了,当你给Proxy.newProxyInstance()方法传递InvocationHandler接口的实现类及其实现类的加载器的时候,Proxy其实就是完全拿到了那个类了,完全可以通过反射和这个类的加载器来创建该InvocationHandler接口的实现类,当你调用被代理类的接口方法rent()时,其实内部就是调用invoke()方法,并且给invoke方法传递你调用的是那个接口方法,还有其传递的参数。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能