代理、委托、回调、钩子、句柄、打桩的区别

news/2024/8/21 1:10:46

文章目录

  • 代理
  • 委托
    • 委托与代理的区别
  • 回调
    • 回调函数
    • 回调函数与普通函数的区别
  • 钩子
    • 广义的钩子
    • 钩子与代理的区别
    • 钩子与委托的区别
    • 钩子与回调函数的区别
  • 句柄
    • 句柄与钩子的区别
  • 打桩
    • 打桩与代理的区别

代理

  代理(proxy):被代理类写好一套 API 的实现对外开放使用,代理类在被代理类的 API 的基础上再封装一层,形成一套与被代理类接口不变的新 API 对外开放使用。

委托

  委托(delegate):委托类事先写好一段程序流程,但某个主要环节的具体实现不由自己决定,而是委托给其它类来实现。委托类会当作这个实现已经写好,直接调用。

委托与代理的区别

  某种程度上来说,代理类有点像委托类,它们都只负责调用,但不负责编写被调用代码具体的实现。最大不同之处在于它们出现的时间顺序正好相反,而且依赖关系不同。

  在代理模式中,被代理类先出现,代理类后出现。被代理类在设计的时候不考虑自已以后会不会被代理。代理类低耦合依赖被代理类,但被代理类自身完全不需要代理类,它不在乎以后是否被代理。

  在委托模式中,委托类先出现,被委托类后出现。委托类知道被委托类以后会出现,但却只负责调用,不负责编写“写死”的代码。委托类与被委托类是一种低耦合、互相依赖的关系,它们双方不能缺少另外一方。

  一般来说,一个活动分为环境、定义、实现、使用。代理类、委托类的设计都是为了遵守设计模式中的单一职责原则,将一个活动的使用与实现分离。可代理类把一个活动的定义与实现耦合在了一起,对外的环境是透明的,因此对内高内聚、对外低耦合。但委托类却把一个活动的环境、定义与使用耦合在了一起,因此局限性较大。

  因此,委托模式的耦合度高于代理模式,因此使用场景较少。通常,如果程序没有高内聚的要求,会使用更低耦合的钩子来代替委托。

  另外,对于某个局部的步骤,代理类会在被代理类基础上增加一些代码,而委托类基本不做任何多余的事情,完全放权给被委托类完成。委托类更多地只是向被委托类提供一种运行环境。

回调

  回调(callback)指的是某函数在执行的时候,由于某些原因,该函数被迫中止执行,交出当前线程的使用权,当前线程转而执行其它函数的过程。因为一般等这个函数执行完毕时,当前线程的使用权会返回到之前中止执行的那个函数中,所以将这个过程称为回调。

  回调中的“调”,指的是那个被迫中止执行的函数对“其它函数”的调用。回调中的“回”,指的是那个“其它函数”以后将会将当前线程使用权返回给那个被迫中止执行的函数。这个“其它函数”往往不是自己编写的函数,而是源自于外源注入。

回调函数

  回调函数指的即为上述“回调”中的“其它函数”。回调函数一般是经过事先设定(传入),等到某事件发生时就被触发的函数。比方说,事件监听器中设定的函数等等。

  有些时候,如果回调函数执行时间很短,有返回值且能控制程序的走向,那么也把它称之为 钩子(hook)。

  在有些编程语言中,如果允许回调函数使用传入处的局部变量,那么也把它称之为 闭包(closure)。

回调函数与普通函数的区别

  回调函数与普通函数的区别在于,一般的函数是自己负责编写实现,自己负责调用。而回调函数是自己负责编写实现,但自己负责调用。自己只是把函数具体实现编写好,然后交给别人来调用。

  另一个区别是,(为了方便,这里将调用回调函数或普通函数的函数称之为主函数)。主函数在调用普通函数时,数据的传输流程一般为,先从普通函数调用时的实参传入,然后到达普通函数的形参,最后由普通函数的返回值到达主函数。对不同的编程语言,有些时候,普通函数也可以通过传入的实参、抛出的异常来将结果反馈给主函数。

  但主函数使用回调函数时,这个过程描述起来就比较复杂了。回调函数通常是异步调用的,因为在主函数传入回调函数时,并没有马上执行该函数,而是改为异步执行,因此回调函数向主函数反馈结果时也一般不能像普通函数一样通过返回值来进行同步阻塞式反馈。通常,这同时还使用了一种称之为 闭包 的技术,来使得回调函数在真正执行时,可以修改主函数的数据,来达到来主函数反馈数据的目的。


【附】

  • 什么是闭包:https://blog.csdn.net/wangpaiblog/article/details/113360870

  • 什么是同步与异步、并行与并发、阻塞与挂起:https://blog.csdn.net/wangpaiblog/article/details/116114098

  • 什么是同步阻塞、同步非阻塞、异步阻塞、异步非阻塞:https://blog.csdn.net/wangpaiblog/article/details/117236684


钩子

  钩子(hook)指的是一个程序预设的子程序跳转入口。在不同的编程语言、不同场景下,钩子可以指预先约定的某一类函数名、某个类的接口引用字段等等。

  钩子在生活中指的是可以钩住其它东西的一种工具,只要这个东西上有能被钩子钩住的圆环即可。如果一个工具上带有钩子,我们就可以在不破坏这个工具的前提下用我们自己的工具连接这个工具,这只需要在我们自己的工具上安装一个圆环即可。在编程中,这里的钩子相当于一个第三方的黑盒,圆环相当于一个对方指定的要实现的接口,只要自己编写的程序遵守了对方的规范并实现了这个接口,就可以在不需要知道和改动黑盒内部结构的情况下让该黑盒使用自己。

  钩子是 IoC 思想的体现。它们有时候也称之为一种程序里的后门。它们体积不大,运行时间不长,但却能控制程序的走向。它是开发者提供给用户的一个功能强大的工具。

  在有些场景中,钩子是一种回调函数(callback)。

广义的钩子

  广义的钩子指的是一个可以控制程序流程的一段代码。但这段代码与程序其它部分的代码属于低耦合,即可以通过不改动其它部分的代码的条件下,任意地更改这段代码来控制程序的走向。

  因此,广义的钩子不仅包括上面介绍的钩子,还包括一些类中预设的布尔函数,比方说,可以对某一系列的类中都设置一个布尔函数,然后用该布尔函数的返回值来决定程序走向,则该布尔函数就是一个广义的钩子。

钩子与代理的区别

  钩子和代理也有些渊源。在某种角度上,含钩子的类也可以看成是一个代理类。但钩子和代理的区别在于,它们设计思路(流程)正好相反。对于代理,一般来说,被代理的类是很早以前就已经设计好了,而代理类依赖于被代理的类且设计时间晚于被代理类。但对于钩子,含钩子的程序往往是提交已经设计好了,之后只需要在使用该程序之前,将“圆环程序”提供该“钩子程序”,就可以使用该“钩子程序”了。可以看出,虽然“钩子程序”是依赖“圆环程序”的,但“圆环程序”的设计时间与“钩子程序”相对独立,是可以晚于“钩子程序”的。另外,“钩子”并未严格限定“圆环程序”的内容,“圆环程序”只需要遵守某种约定的规范,其内容可以自由发挥。这就是 IoC 思想。如果硬要把代理中的概念与钩子相对应,那么从这个角度上,代理与钩子的区别在于,对于代理,可以自由发挥的是代理类,而对于钩子,则是被代理类。

钩子与委托的区别

  钩子可以看作是委托的升级版或者是特别版,其耦合度比委托要低。


在下面的这些情况下,应当设计成钩子而不是委托:

  • 程序已经抽象出来一套生命周期

  • 活动的实现与使用之间没有高内聚的要求

  • 需要将接口对第三方暴露

  • 对外暴露的接口的返回值将决定程序的走向

  • 对外暴露的接口的实现不是一个耗时的操作


钩子与回调函数的区别

  钩子与回调函数这两个词的意思非常接近,只是描述事物的侧重点有些不同,就像等边三角形与等角三角形,因此经常混用。


钩子相对于普通的回调函数,通常有如下特点:

  • 内容短小、操作步骤很基本、耗时小

  • 可以通过其返回值来控制程序走向

  • 一般不会开启新线程或后台任务

回调函数相对于钩子,通常有如下特点:

  • 回调函数由事件触发,且允许反复触发

  • 对于 UI 领域,这种函数往往是 纯函数,且返回值常常为空(void)

  • 当程序的运行轨迹改变时可以触发它,但它不会主动控制程序走向


关于什么是纯函数,可见笔者的另一篇博客:

什么是纯函数?:
https://blog.csdn.net/wangpaiblog/article/details/114005888


句柄

  句柄(handle)指的是一种通过它能够访问程序内部,甚至控制程序的某种数值。在不同的编程语言、不同场景下,它可以指的是一种内存地址、指针、类对象等等。


【注意】

  句柄的英文是 handle,而不是 handler。但 handler 也是一个编程中的术语,它和 handle 完全不是同一个东西。但由于英文语法与中文语法的区别,很难找到一个没有用过的两个字的中文词汇来翻译它。handler 实际上是一种事件处理程序(处理器),英文解释是 callback routine,因此,它的意思更接近回调函数(callback)或者钩子(hook)。所以,handler 并不是句柄的意思。


句柄与钩子的区别

  钩子是开发者提供给用户的一个功能强大的工具。就功能强大而言,这有点类似于句柄。但从使用方法来说,它们更像是相反的东西。

  句柄提供了一些可供调用的 API,而钩子则要求自己实现这些 API 的内容,然后注入到程序中。

打桩

  在编程中,桩(stub)是指用于模拟真实环境的代码段。在开发者测试中,常常需要模拟真实的环境来用于测试。因为构建真实的环境往往成本很大或者不可能,这就需要模拟。在开发者测试中,一个大型的项目必须要分解成各个基本的单元,先进行单元测试(UT),然后进行集成测试(IT),最后进行系统测试(ST)。分开测试的各个部分的碎片化的模拟环境称为桩。桩一般就具体为,对真实环境进行模拟所编写的函数。对桩函数的编写称为打桩。

打桩与代理的区别

  代理和打桩都有一种伪装、等效替代的思想。桩函数相当于代理类,都喜欢对外伪装成使用者原来想要使用的东西。但区别在于打桩是测试领域使用的术语,而代理是开发领域使用的术语。


http://lihuaxi.xjx100.cn/news/1216718.html

相关文章

chatgpt赋能python:如何重新运行Python程序:完整指南

如何重新运行Python程序:完整指南 Python是最受欢迎的编程语言之一,因为其语法简单易懂,使得编写高效可读性代码更加轻松。但在编程过程中经常会出现需要重新运行程序的情况,本文将为您介绍如何重新运行Python程序。 重新运行Py…

chatgpt赋能python:Python如何运行最方便

Python 如何运行最方便 Python 是一种高级编程语言,被广泛使用于各类领域。由于其简单易学,可读性高,适用于不同平台的特性,Python 已成为计算领域、Web 开发、数据分析等领域的首选语言之一。如果您正在学习 Python 或需要对其进…

A股月份效应 | Python量化A股市场魔咒,5穷6绝7翻身准确吗?| 邢不行

A股有很多广为流传的谚语,它们大多源于投资者对交易经验的总结和共识。 比如我们之前验证过的散户反买别墅靠海、跳空必回补等谚语。 今天我们要验证的,是五穷六绝七翻身这句谚语。 它的意思是A股在5月、6月可能会跌的很惨,到7月会开始反弹回…

单马达可换档六足机器人前进功能的实现

1. 运动功能说明 本文示例将实现R046样机单马达可换档六足机器人前进的功能。 2. 结构说明 本样机只有一个圆周舵机,却可以通过换挡机构实现前进和转向两种行走姿态。 样机由一个圆周舵机带动一个等速齿轮组(下图所示两枚蓝色齿轮)&#xff0…

Jsp+sql智能交通道路管理系统(论文+任务书+外文翻译+开题报告+文献综述)

电子警察是“智能电子警察监测系统”的简称,它是一套高科技电子设备,最初是为维护交通执法提供了一种先进手段。以往许多城市在某些交通场合,由于没有有效的执法手段造成执法困难,例如:无人值守的路口;单行线;禁行、限时道路;限车型车道;主、辅路进出口;紧急停车带;…

STM32F103下载的SWJ接口禁用问题

前言 在STM32中有一些引脚的主功能不是实现GPIO的功能,而是用作调试接口。就比如我们常用的ST-LINK下载器,就是通过SWD接口给STM32下载程序的。SWJ接口包括SWD和JTAG两种。 环境 STM32F103C6T6核心板STM32CubeMX生成的HAL库文件 基础 SWJ接口&#x…

【SQL武林秘籍】玩转表及其数据

目录 📖前言 😀数据库约束类型 1️⃣not null 非空约束 2️⃣unique 唯一约束 3️⃣default 默认值约束 4️⃣primary key 主键约束 5️⃣foreign key 外键约束 6️⃣check 限制约束 😉新增(insert select) 😄查询(进…

阶乘约数猴子分香蕉

题目 定义阶乘n!123⋅⋅⋅n。 请问 100!(100 的阶乘)有多少个正约数。 思路 不会写,还以为去算100!各个乘数的组合呢!看了题解才发现,是一个跟数理有关系的题目。首先:任何一个正整数都能被表示…