设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
120453 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

48 | 代理模式:代理在RPC、缓存、监控等场景中的应用

前面几节,我们学习了设计模式中的创建型模式。创建型模式主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码。
其中,单例模式用来创建全局唯一的对象。工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建复杂对象,可以通过设置不同的可选参数,“定制化”地创建不同的对象。原型模式针对创建成本比较大的对象,利用对已有对象进行复制的方式进行创建,以达到节省创建时间的目的。
从今天起,我们开始学习另外一种类型的设计模式:结构型模式。结构型模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题。结构型模式包括:代理模式、桥接模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式。今天我们要讲其中的代理模式。它也是在实际开发中经常被用到的一种设计模式。
话不多说,让我们正式开始今天的学习吧!

代理模式的原理解析

代理模式(Proxy Design Pattern)的原理和代码实现都不难掌握。它在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。我们通过一个简单的例子来解释一下这段话。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(105)

  • 最新
  • 精选
  • Kevin
    基于继承的静态代理实现的demo中稍微有些瑕疵。 login() 和register() 方法应该直接调用super.login() 和 super.register() ,然后再super前后插入额外的代码 。这样更像在代理,而不是在继承修改父类。给争哥提个不成熟的小建议。

    作者回复: 我看看,多谢!

    2
  • 海贼王
    文章很有实用性,对于拓展思路很有帮助

    作者回复: 嗯嗯 多谢~!

  • 成长型思维
    代理模式也叫中介模式吗

    作者回复: 不是,两个不同的模式

  • 小兵
    组合模式的优点在于更加灵活,对于接口的所有子类都可以代理,缺点在于不需要扩展的方法也需要进行代理。 继承模式的优点在于只需要针对需要扩展的方法进行代理,缺点在于只能针对单一父类进行代理。
    8
    173
  • java中,动态代理的实现基于字节码生成技术(代码里就是newProxyInstance片段),可以在jvm运行时动态生成和加载字节码,类似的技术还有asm,cglib,javassist,平时编译java用的javac命令就是字节码生成技术的"老祖宗" java中用到字节码生成技术的还有JSP编译器.AOP框架,反射等等 深入理解java虚拟机第三版里对动态代理的描述: 动态代理中所说的"动态",是针对使用Java代码实际编写了代理类的"静态"代理而言的,它的优势不在于省去了编写代理类那一点编码工作量,而是实现了可以在原始类和接口还未知的时候,就确定了代理类的行为,当代理类与原始类脱离直接联系后,就可以很灵活的重用于不同的应用场景之中
    2
    125
  • trier
    粗略“翻译”至PHP,中间省略了很多关键的判断,主要是想知道有多少PHPer在看。 interface IUserController { public function login(String $telephone, String $password); public function register(String $telephone, String $password); } class UserController implements IUserController { public function login(String $telephone, String $password) { echo 'is Login' . PHP_EOL; } public function register(String $telephone, String $password) { } } class MetricsCollector { public function recordRequest($requestInfo) { } } class RequestInfo { public function __construct($apiName, $responseTime, $startTimestamp) { } } class MetricsCollectorProxy { private $proxiedObject; private $metricsCollector; public function __construct(MetricsCollector $metricsCollector) { $this->metricsCollector = $metricsCollector; } public function createProxy(object $object) { $this->proxiedObject = $object; return $this; } public function __call($method, $arguments) { $ref = new ReflectionClass($this->proxiedObject); if (!$ref->hasMethod($method)) throw new Exception("method not existed"); $method = $ref->getMethod($method); $startTimestamp = time(); $userVo = $this->callMethod($method, $arguments); $endTimeStamp = time(); $responseTime = $endTimeStamp - $startTimestamp; $requestInfo = new RequestInfo("login", $responseTime, $startTimestamp); $this->metricsCollector->recordRequest($requestInfo); return $userVo; } private function callMethod(\ReflectionMethod $method, $arguments) { //前置判断省略 $method->invokeArgs($this->proxiedObject, $arguments); } } $proxy = new MetricsCollectorProxy(new MetricsCollector); $userController = $proxy->createProxy(new UserController); $userController->login(13800138000, 'pwd');
    7
    32
  • LJK
    是时候展示我动态语言Python的彪悍了,通过__getattribute__和闭包的配合实现,其中有个注意点就是在获取target时不能使用self.target,不然会递归调用self.__getattribute__导致堆栈溢出: class RealClass(object): def realFunc(self, s): print(f"Real func is coming {s}") class DynamicProxy(object): def __init__(self, target): self.target = target def __getattribute__(self, name): target = object.__getattribute__(self, "target") attr = object.__getattribute__(target, name) def newAttr(*args, **kwargs): print("Before Calling Func") res = attr(*args, **kwargs) print("After Calling Func") return res return newAttr
    5
    28
  • 迷羊
    Java中的动态代理原理就是运行的时候通过asm在内存中生成一份字节码,而这个字节码就是代理类的字节码,通过System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");设置可以保存这份字节码,反编译后看下其源码就知道Java中的动态代理是什么原理了。
    24
  • 辣么大
    感谢争哥,今天终于学会了“动态代理” 还是要动手试试,代码在这是 https://bit.ly/37UqLNf 学有余力的小伙伴,附上一些资料吧: https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html https://www.baeldung.com/java-dynamic-proxies
    3
    17
  • 不似旧日
    笔记: - 什么是代理模式:它在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。 - 代理模式得实现: - 静态代理 1. 实现被代理对象口: 要求被代理类和代理类同时实现相应的一套接口,通过代理类调用重写接口的方法,实际上调用的是原始对象的同样的方法。 2. 继承被代理对象:代理类继承原始类,然后扩展附加功能。 - 动态代理 : 在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。 1. jdk动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 2. cglib动态代理是利用asm开源包,对被代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
    2
    11
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部