代理模式:
为其他对象提供一种代理以控制对这个对象的访问。
代理模式是对象的结构模式,代理模式给某一个对象提供一个代理对象,并由此代理对象控制对原代理对象的引用。代理模式不应该让用户感觉到代理的存在,所以代理对象和原对象的对外的调用接口是一致的。
代理模式一般包括三个角色:
- 抽象主题角色(Subject):它的作用是统一接口。此角色定义了真实主题角色和代理主题角色共用的接口,这样就可以在使用真实主题角色的地方使用代理主题角色。
- 真实主题角色(RealSubject):隐藏在代理角色后面的真实对象。
- 代理主题角色(ProxySubject):它的作用是代理真实主题,在其内部保留了对真实主题角色的引用。它与真实主题角色都继承自抽象主题角色,保持接口的统一。它可以控制对真实主题的存取,并可能负责创建和删除真实对象。代理角色并不是简单的转发,通常在将调用传递给真实对象之前或之后执行某些操作,当然你也可以只是简单的转发。 与适配器模式相比:适配器模式是为了改变对象的接口,而代理模式并不能改变所代理对象的接口。
思维导图:

使用场景:实现延迟加载。
<?php/**
* Proxy design pattern (lazy loading)@global
* 实现了图片的延迟加载
*/
/* 抽象主题角色,提供统一接口 */
interface ImageInterface
{
public function display();
}
/* 真是主题角色,就是需要被代理的类 */
class Image implements ImageInterface
{
protected $filename;
public function __construct($filename) {
$this->filename = $filename;
$this->loadFromDisk();
}
protected function loadFromDisk() {
echo "Loading {$this->filename}\n";
}
public function display() {
echo "Display {$this->filename}\n";
}
}
/* 代理主题角色,原图片类在实例化时就把图片加载到内存了,用代理修改为display时才执行加载 */
class ProxyImage implements ImageInterface
{
protected $id;
protected $image;
protected $filename;
public function __construct($filename) {
$this->filename = $filename;
}
public function display() {
if (null === $this->image) { //缓存
$this->image = new Image($this->filename);
}
return $this->image->display();
}
}
//调用Image类,在实例化时就加载到内存了,如果没调display就浪费了
$filename = 'test.png';
$image1 = new Image($filename); // 已经加载到内存
echo $image1->display();
//代理类是在display时才把图片从磁盘加入内存
$image2 = new ProxyImage($filename);
echo $image2->display(); // 此时才加载到内存
echo $image2->display(); // 直接从内存获取
通过反射来代理多个对象,这种方式有缺陷,看代码体会!具体使用还看应用场景
<?PHP
/**
* 使用反射实现代理工厂
*/
/**
* 真实主题角色 A
*/
final class RealSubjectA {
public function __construct() {
}
public function actionA() {
echo "actionA method in RealSubject A <br />\r\n";
}
}
/**
* 真实主题角色 B
*/
final class RealSubjectB {
public function __construct() {
}
public function actionB() {
echo "actionB method in RealSubject B <br />\r\n";
}
}
/**
* 代理主题角色
*/
final class ProxySubject {
private $_real_subjects = NULL;
public function __construct() {
$this->_real_subjects = array();
}
/**
* 动态添加真实主题
* @param type $subject
*/
public function addSubject($subject) {
$this->_real_subjects[] = $subject;
}
public function __call($name, $args) {
foreach ($this->_real_subjects as $real_subject) {
/* 使用反射获取类及方法相关信息 */
$reflection = new ReflectionClass($real_subject);
/* 如果不存在此方法,下一元素 */
if (!$reflection->hasMethod($name)) {
continue;
}
$method = $reflection->getMethod($name);
/* 判断方法是否为公用方法并且是否不为抽象方法 */
if ($method && $method->isPublic() && !$method->isAbstract()) {
$this->_beforeAction();
$method->invoke($real_subject, $args);
$this->_afterAction();
break;
}
}
}
/**
* 请求前的操作
*/
private function _beforeAction() {
echo "Before action in ProxySubject<br />\r\n";
}
/**
* 请求后的操作
*/
private function _afterAction() {
echo "After action in ProxySubject<br />\r\n";
}
}
$subject = new ProxySubject();
$subject->addSubject(new RealSubjectA());
$subject->addSubject(new RealSubjectB());
$subject->actionA();
$subject->actionB();
来源:https://www.cnblogs.com/leezhxing/p/4170084.html