一、定义:
为其他对象提供一种代理以控制对这个对象的访问。
二、角色组成:
Subject抽象主题:声明真是主题与代理的共同接口方法,可以是一个抽象类或接口。
RealSubject真实主题:定义了代理表示的真实对象,执行具体的逻辑和方法。
ProxySubject代理:持有对真实主题的引用,实现接口方法中调用真实主题对应的接口方法。
Client客户:使用代理的示例,通过调用代理的方法来实现对真实主题的调用。
三、代理类型:
1.静态代理:手动创建代理类直接持有目标对象的引用。
2.动态代理:运行时动态生成代理类,如JDK的动态代理,CGLIB等。
3.远程代理:跨进程通信的代理,如Android的AIDL机制。
四、简单实现:
静态代理
1.抽象主题
public interface FileLoader {
String readFile(String path);
}
2.真实主题
public class RealFileLoader implements FileLoader {
@Override
public String readFile(String path) {
// 模拟读取文件内容
return "File content: " + path;
}
}
3.代理
public class FileLoaderProxy implements FileLoader {
private RealFileLoader realFileLoader;
private boolean hasPermission;
public FileLoaderProxy(boolean hasPermission) {
this.hasPermission = hasPermission;
}
@Override
public String readFile(String path) {
// 延迟初始化真实对象
if (realFileLoader == null) {
realFileLoader = new RealFileLoader();
}
// 权限校验
if (!hasPermission) {
return "Error: Permission denied!";
}
// 调用真实对象方法
return realFileLoader.readFile(path);
}
}
4.客户端调用
public class Main {
public static void main(String[] args) {
// 有权限的用户
FileLoader proxy1 = new FileLoaderProxy(true);
System.out.println(proxy1.readFile("/data/test.txt"));
// 输出:File content: /data/test.txt
// 无权限的用户
FileLoader proxy2 = new FileLoaderProxy(false);
System.out.println(proxy2.readFile("/data/secret.txt"));
// 输出:Error: Permission denied!
}
}
动态代理
1.抽象主题
public interface DataService {
void saveData(String data);
void deleteData(String id);
}
2.真实主题
public class RealDataService implements DataService {
@Override
public void saveData(String data) {
System.out.println("Saving data: " + data);
}
@Override
public void deleteData(String id) {
System.out.println("Deleting data with ID: " + id);
}
}
3.动态代理执行
public class LoggingHandler implements InvocationHandler {
private Object target; // 目标对象
public LoggingHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 记录调用日志
System.out.println("Method called: " + method.getName());
if (args != null) {
System.out.println("Arguments: " + Arrays.toString(args));
}
// 调用真实对象方法
Object result = method.invoke(target, args);
// 记录返回结果
System.out.println("Method completed: " + method.getName());
return result;
}
}
4.生成动态代理调用
public class Main {
public static void main(String[] args) {
// 创建真实对象
DataService realService = new RealDataService();
// 创建动态代理
DataService proxy = (DataService) Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
realService.getClass().getInterfaces(),
new LoggingHandler(realService)
);
// 通过代理调用方法
proxy.saveData("Hello, Proxy!");
proxy.deleteData("123");
}
}
五、优缺点
优点:
1.控制对象访问,增强安全性。
2.支持延迟加载,优化性能。
3.解耦客户端与目标对象
缺点:
1.增加代码复杂度,需要额外增加代理类。
2.动态代理可能降低运行效率。
3.远程代理需要处理网络或跨进程问题。