设计模式-结构型-代理模式(Proxy)
参考文献
代理模式
- 让你能够提供对象的替代品或其占位符. 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理.
组件
- 抽象主题(Subject): 定义了真实主题和代理主题之间的共同接口,客户端通过该接口访问真实主题.
- 真实主题(Real Subject): 定义了真实对象的具体业务逻辑.代理对象通过调用真实主题来完成实际的操作.
- 代理主题(Proxy Subject): 实现了抽象主题接口,并在其内部维护了一个引用,指向真实主题对象.代理主题负责控制对真实主题对象的访问,并且可以在真实主题的基础上增加额外的功能,如权限验证、缓存等.
- 客户端(Client): 通过抽象主题接口与代理主题进行交互.客户端不需要知道真实主题的存在,只需要通过代理主题完成相应的操作.
实现方式
-
定义抽象主题接口: 首先,需要定义一个抽象主题接口,该接口定义了真实主题和代理主题之间的共同方法.
1
2
3
4public interface FileServer {
void uploadFile(String fileName);
void downloadFile(String fileName);
} -
实现真实主题类: 创建真实主题类,实现抽象主题接口,并实现具体的业务逻辑.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class RemoteFileServer implements FileServer {
public void uploadFile(String fileName) {
System.out.println("正在上传文件: " + fileName);
// 连接远程服务器,执行上传操作
// ...
System.out.println("上传完成");
}
public void downloadFile(String fileName) {
System.out.println("正在下载文件: " + fileName);
// 连接远程服务器,执行下载操作
// ...
System.out.println("下载完成");
}
} -
创建代理主题类: 创建代理主题类,也实现抽象主题接口.在代理主题类中,维护一个对真实主题对象的引用,并且可以在方法调用前后进行额外的操作.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class FileServerProxy implements FileServer {
private FileServer fileServer;
public FileServerProxy() {
this.fileServer = new RemoteFileServer();
}
public void uploadFile(String fileName) {
// 执行额外操作,如权限验证
if (checkPermission()) {
// 调用真实主题的方法
fileServer.uploadFile(fileName);
} else {
System.out.println("无权限进行文件上传");
}
}
public void downloadFile(String fileName) {
// 执行额外操作,如日志记录
logDownload(fileName);
// 调用真实主题的方法
fileServer.downloadFile(fileName);
}
private boolean checkPermission() {
// 检查用户权限逻辑
// ...
return true; // 假设所有用户都有上传权限
}
private void logDownload(String fileName) {
// 记录下载日志逻辑
// ...
System.out.println("正在下载文件: " + fileName);
}
} -
客户端使用代理对象: 在客户端中,使用代理主题对象进行操作.客户端只需通过抽象主题接口与代理主题交互,无需直接与真实主题打交道.
1
2
3
4
5
6
7public class Client {
public static void main(String[] args) {
FileServer fileServer = new FileServerProxy();
fileServer.uploadFile("example.txt");
fileServer.downloadFile("example.txt");
}
}
使用场景
-
延迟初始化(虚拟代理): 当有一个重量级的服务对象,并且只有在需要时才希望进行初始化,可以使用代理模式来延迟初始化,减少系统资源的消耗.
-
访问控制(保护代理): 当希望限制特定客户端对服务对象的访问权限时,可以使用代理模式来实现访问控制,只允许特定的客户端进行访问.
-
本地执行远程服务(远程代理): 当服务对象位于远程服务器上时,可以使用代理模式在本地创建一个代理对象,通过网络与远程对象进行通信,实现本地调用远程服务.
-
记录日志请求(日志记录代理): 当需要对对服务对象的请求进行日志记录时,可以使用代理模式来记录请求日志,方便后续的调试和问题排查.
-
缓存请求结果(缓存代理): 当客户端请求的结果具有重复性,并且结果的计算成本较高时,可以使用代理模式来缓存请求结果,提高系统性能.
-
智能引用: 当某个重量级对象没有客户端使用时,可以使用代理模式来立即销毁该对象,以节省资源.
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!