博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
代理模式
阅读量:6419 次
发布时间:2019-06-23

本文共 2975 字,大约阅读时间需要 9 分钟。

代理模式

为其他对象提供一种代理以控制对这个对象的访问。

代理模式是对象的结构模式,代理模式给某一个对象提供一个代理对象,并由此代理对象控制对原代理对象的引用。代理模式不应该让用户感觉到代理的存在,所以代理对象和原对象的对外的调用接口是一致的。

 

代理模式一般包括三个角色:

 

  • 抽象主题角色(Subject):它的作用是统一接口。此角色定义了真实主题角色和代理主题角色共用的接口,这样就可以在使用真实主题角色的地方使用代理主题角色。
  • 真实主题角色(RealSubject):隐藏在代理角色后面的真实对象。
  • 代理主题角色(ProxySubject):它的作用是代理真实主题,在其内部保留了对真实主题角色的引用。它与真实主题角色都继承自抽象主题角色,保持接口的统一。它可以控制对真实主题的存取,并可能负责创建和删除真实对象。代理角色并不是简单的转发,通常在将调用传递给真实对象之前或之后执行某些操作,当然你也可以只是简单的转发。 与适配器模式相比:适配器模式是为了改变对象的接口,而代理模式并不能改变所代理对象的接口。

 

 

思维导图:

 

使用场景:实现延迟加载。

 

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(); // 直接从内存获取

 

通过反射来代理多个对象,这种方式有缺陷,看代码体会!具体使用还看应用场景

\r\n"; }}/** * 真实主题角色 B */final class RealSubjectB { public function __construct() { } public function actionB() { echo "actionB method in RealSubject B
\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
\r\n"; } /** * 请求后的操作 */ private function _afterAction() { echo "After action in ProxySubject
\r\n"; }}$subject = new ProxySubject();$subject->addSubject(new RealSubjectA());$subject->addSubject(new RealSubjectB());$subject->actionA();$subject->actionB();

 

转载地址:http://fslra.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
ifconfig:command not found的解决方法
查看>>
计算机是怎么存储数字的
查看>>
Codeforces Round #369 (Div. 2) A. Bus to Udayland 水题
查看>>
adb上使用cp/mv命令的替代方法(failed on '***' - Cross-device link解决方法)
查看>>
C++标准库简介、与STL的关系。
查看>>
Spring Boot 3 Hibernate
查看>>
查询EBS请求日志的位置和名称
查看>>
大型机、小型机、x86服务器的区别
查看>>
J2EE十三个规范小结
查看>>
算法(第四版)C#题解——2.1
查看>>
网关支付、银联代扣通道、快捷支付、银行卡支付分别是怎么样进行支付的?...
查看>>
大数据开发实战:Stream SQL实时开发一
查看>>
C++返回引用的函数例程
查看>>
dll 问题 (转)
查看>>
使用sql生成UUID
查看>>
REST API用得也痛苦
查看>>
test for windows live writer plugins
查看>>
Tiny210 U-BOOT(二)----配置时钟频率基本原理
查看>>
代理模式
查看>>