关于代理模式这一篇就够了

代理模式的概念

代理模式(Proxy Pattern)是程序设计中的一种设计模式,其定义是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式的优缺点

优点

  1. 职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完整事务,附带的结果就是编程简洁清晰。
  2. 降低耦合度:在一定程度上降低了系统的耦合度,扩展性好。
  3. 保护作用:代理对象可以在客户端和目标对象之间起到中介的作用,这样可以保护目标对象。
  4. 增强功能:可以增强目标对象的功能。

缺点

  1. 增加类的数量:代理模式会造成系统设计中类的数量增加。
  2. 处理速度变慢:在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢。
  3. 增加复杂度:增加了系统的复杂度。

代理模式的应用场景

  1. 远程代理:当对象位于远程服务器上时,可以使用代理模式来进行远程访问。代理对象可以隐藏实际对象的细节,客户端可以通过代理对象来访问远程对象,而无需了解远程的实现细节。
  2. 虚拟代理:当创建一个对象需要很长的时间时,可以使用代理模式来延迟对象的创建。
  3. 安全代理:当需要控制对对象的访问权限时,可以使用代理模式。
  4. 缓存代理:当需要缓存对象的计算结果时,可以使用代理模式。

代理模式的代码实现

代理模式的实现通常包括以下几个部分:

  1. 抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
  2. 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  3. 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

以下是一个简单的静态代理模式的Java代码示例:

// 抽象角色
public interface IProduct {
void produce();
}
// 真实角色
public class RealProduct implements IProduct {
@Override
public void produce() {
System.out.println("生产产品...");
}
}
// 代理角色
public class ProxyProduct implements IProduct {
private RealProduct realProduct;
public ProxyProduct(RealProduct realProduct) {
this.realProduct = realProduct;
}
@Override
public void produce() {
System.out.println("代理开始...");
realProduct.produce();
System.out.println("代理结束...");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealProduct realProduct = new RealProduct();
ProxyProduct proxyProduct = new ProxyProduct(realProduct);
proxyProduct.produce();
}
}

在这个示例中,RealProduct是真实角色,ProxyProduct是代理角色,它们都实现了IProduct接口。在客户端代码中,我们首先创建了一个RealProduct对象,然后将其传递给ProxyProduct的构造函数以建立代理关系。最后,我们调用proxyProduct.produce()方法,这个方法会先输出“代理开始...”,然后调用真实角色的produce()方法生产产品,最后输出“代理结束...”。

动态代理模式的实现通常依赖于反射机制,在Java中,可以使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。动态代理允许在运行时动态地创建代理对象,而无需为每个需要代理的类手动编写代理类。

以下是一个Java中动态代理模式的示例代码:

首先,定义一个接口,这个接口将被代理的类需要实现:

public interface IProduct {
void produce();
}

然后,定义一个实现类,这个类实现了上面的接口:

public class RealProduct implements IProduct {
@Override
public void produce() {
System.out.println("生产产品...");
}
}

接下来,定义一个InvocationHandler的实现类,这个类负责在调用代理对象的方法时,执行相应的操作:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProductInvocationHandler implements InvocationHandler {
private Object target; // 被代理的对象
public ProductInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始...");
Object result = method.invoke(target, args); // 调用被代理对象的方法
System.out.println("代理结束...");
return result;
}
}

最后,客户端代码使用Proxy.newProxyInstance()方法动态地创建代理对象,并调用其方法:

import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
RealProduct realProduct = new RealProduct();
ProductInvocationHandler handler = new ProductInvocationHandler(realProduct);
// 动态创建代理对象,需要三个参数:类加载器,被代理对象的接口,InvocationHandler实现类
IProduct proxyProduct = (IProduct) Proxy.newProxyInstance(
realProduct.getClass().getClassLoader(),
realProduct.getClass().getInterfaces(),
handler
);
// 调用代理对象的方法,会自动调用InvocationHandler的invoke方法
proxyProduct.produce();
}
}

在这个示例中,Proxy.newProxyInstance()方法接受三个参数:

  1. 类加载器(ClassLoader):通常使用被代理对象的类加载器。
  2. 被代理对象的接口(Class<?>[]):被代理对象实现的接口列表,代理对象将实现这些接口。
  3. InvocationHandler实现类:在调用代理对象的方法时,这个方法会被调用。

注意,动态代理只能代理接口,如果类没有实现任何接口,则无法使用动态代理模式。如果需要代理类(而不是接口),可以考虑使用CGLIB库等第三方库来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值