本文目录导读:

是的,PHP中的代理模式(Proxy Pattern) 主要用于控制对对象的访问,它通过引入一个代理对象,在客户端和真实对象之间起到中介作用,从而在不修改原有代码的前提下,增加额外的控制逻辑。
代理模式的核心作用(控制访问的几种典型场景)
-
延迟加载(虚拟代理)
当创建真实对象的成本很高时(如读取大文件、数据库查询、远程服务调用),代理可以在首次访问时才实例化对象,避免不必要的资源浪费。 -
访问权限控制(保护代理)
代理可以检查调用者的身份或权限,只有满足条件时才将请求转发给真实对象。 -
日志记录/性能监控(日志代理)
在调用真实对象方法前后,记录日志、统计执行时间或缓存结果。 -
远程代理
代理隐藏对象位于不同地址空间或网络中的细节,让客户端如同操作本地对象一样。 -
智能引用
当真实对象被多个客户端共享时,代理可以管理引用计数,或在对象不再使用时释放资源。
PHP 示例:保护代理(控制访问权限)
假设有一个敏感操作类 RealFileUploader,只有管理员才能调用,代理模式实现如下:
<?php
// 1. 定义真实对象和代理的共同接口(让代理可以替换真实对象)
interface FileUploader {
public function upload($filePath);
}
// 2. 真实对象:执行实际的文件上传
class RealFileUploader implements FileUploader {
public function upload($filePath) {
echo "文件 {$filePath} 已成功上传到服务器。\n";
// 实际上传逻辑...
}
}
// 3. 代理对象:在调用真实对象前进行权限检查
class FileUploaderProxy implements FileUploader {
private $realUploader;
private $userRole;
public function __construct($userRole) {
$this->userRole = $userRole;
// 延迟加载:先不创建真实对象,节省资源
$this->realUploader = null;
}
public function upload($filePath) {
// 访问控制:只有管理员才能上传
if ($this->userRole !== 'admin') {
throw new \Exception("权限不足:只有管理员才能上传文件。");
}
// 延迟实例化真实对象(首次使用时才创建)
if ($this->realUploader === null) {
$this->realUploader = new RealFileUploader();
}
// 可以在这里添加日志记录
echo "[日志] 用户角色 {$this->userRole} 正在上传文件:{$filePath}\n";
// 转发请求给真实对象
return $this->realUploader->upload($filePath);
}
}
// 4. 客户端使用
try {
// 模拟普通用户上传
$userProxy = new FileUploaderProxy('user');
$userProxy->upload('report.pdf'); // 会抛出异常
} catch (\Exception $e) {
echo "错误:" . $e->getMessage() . "\n";
}
// 管理员上传成功
$adminProxy = new FileUploaderProxy('admin');
$adminProxy->upload('confidential.docx');
输出结果:
错误:权限不足:只有管理员才能上传文件。
[日志] 用户角色 admin 正在上传文件:confidential.docx
文件 confidential.docx 已成功上传到服务器。
代理模式 vs 其他模式的区别
| 模式 | 控制访问特点 |
|---|---|
| 代理 | 控制对单个对象的访问,增加额外操作(权限、日志、延迟加载) |
| 装饰器 | 动态地为对象添加新行为,但不控制访问,客户端仍直接操作原对象 |
| 适配器 | 转换接口使不兼容的类能协作,不控制访问,解决接口不匹配问题 |
- 是的,代理模式的核心目的就是控制对象访问,通过拦截对真实对象的操作来实现权限验证、延迟初始化、日志记录等。
- 在 PHP 中,代理通常实现与真实对象相同的接口,让客户端无感切换。
- 它特别适合需要附加控制逻辑(如安全、性能、监控)但不想修改原有业务类的场景。