强大的wrapper

article/2025/10/22 20:41:00

最近在看大数据和容器相关的东西,发现有一个模式被反复使用到,关键是被用的很恰当且优雅,并能在这些关键技术中都发挥着至关重要的核心作用。我想你已经猜到了,他就是Eminem——强大的rapper——哦,不对,是wrapper。接下来,这篇文章我就带大家看看,wrapper这玩意有什么特别之处,为啥这么有用?

1. 什么是wrapper

Wrapper就是包装的意思,广义上来说,Decorator和Adapter设计模式都属于Wrapper,只是二者的意图(intent)不一样。借用stackflow上一哥们的回答:

Decorator:

Allows objects to be composed/add capabilities by wrapping them with a class with the same interface.

Adapter:

Allows you to wrap an object without a known interface implementation so it adheres to an interface. The point is to "translate" one interface into another.

Wrapper:

Never heard of this as a design pattern, but I suppose it's just a common name for the above

大意是说Decorator是用组合的方式增强功能,而Adapter是为了做接口转换,二者都是采用wrapper的方式来做到这一点,形式是一样的,但意图不一样。

2. 流式计算中的wrapper

谈到wrapper(在本文中,你可以认为wrapper就是decorator),我认为使用最到位的,非流式计算莫属。从Java的IO流,到Java Stream,到Spark,Flink到处都能看到wrapper的身影。

2.1 Java IO流

我们先从Java IO流看起,假如现在我们需要从一个文件中读取信息打印到console,我们可以使用以下的方式:

Reader in = new BufferedReader(               // 3. 缓冲字符,提升效率new InputStreamReader(                    // 2. 将字节流转换成字符流new FileInputStream("path"), "GBK") // 1. 读取文件的字节流    )
)

其执行过程如下图所示,首先从文件中读取字节流,然后放入字节缓冲区,例如“中”字,他的GBK编码是两个字节——D6D0,那么在InputStreamReader中等到这个字符形成以后,再输送到BufferedReader的字符缓冲区,当缓冲区满了以后,再溢写到console。

e2d71b5cb57d349ab2b615de2598413c.png

IO流的这种做法就是一种典型的wrapper,也就是decorator装饰者设计模式的实现。通过层层包装,我们获得了更强功能的流处理能力。

2.2 Spark中的RDD

RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合。

Spark支持两个类型(算子)操作:Transformation和Action,主要做的是就是将一个已有的RDD生成另外一个RDD。Transformation具有lazy特性(延迟加载)。Transformation算子的代码不会真正被执行。只有当我们的程序里面遇到一个action算子的时候,代码才会真正的被执行。这种设计让Spark更加有效率地运行。

其中Transformation等价于Java Stream中的中间操作(Intermediate operations),而Action和Java Stream的结束操作(Terminal operations)表达的是一个意思,它们只是实现方式不一样,Java Stream是使用pipeline,而spark则采用了wrapper的方式来达到lazy的特性。以wordCount为例,它在spark中的scala实现如下:

//1. new HadoopRDD()
val lines: RDD[String] = sparkContext.textFile("path")//2. new MapPartitionsRDD(hadoopRdd) - flatMap
val words: RDD[String] = lines.flatMap(_.split(regex=" "))//3. new MapPartitionsRDD(mapPartitionsRdd) - map
val wordToOne = words.map(word=>(word, 1))//4. new ShuffledRDD(mapPartitionsRdd)
val wordToSum:RDD[(String, Int)] = wordToOne.reduceByKey(_+_)//5. collect
val array: Array[(String, Int)] = wordToSum.collect()

其在runtime被执行时,实际上,构建的是一个如下图所示的wrapper,也就是说,当flatmap被调用时,并不会真正执行flatmap这个动作,而是构建了一个MapPartitionsRDD包装了HadoopRDD,以此类推,直到collect方法被调用时,前序的转换指令(transformation)才会被真正执行。

2642908c3ea9d127de58d1c52b2079e9.png

同样的道理也适用于Flink,Flink中的各种transform算子也是通过这种wrapper的方式构建出来的。

3. wrapper的背后思想

通过上面的案例,可以看到wrapper这个模式的确很有用,再往下深挖一下,我们可以发现其背后隐藏着更深刻的设计道理——即分层和OCP。

3.1 分层

表面上是包装,其背后暗含的是一种分层结构。“复杂性常常以层次结构的形式存在。复杂的系统有一些相关的子系统组成,这些子系统又有自己的系统,如此下去,直到达到某种最低层次的基本组件。”

因此,wrapper这种构建类似洋葱圈层次结构的能力,正是构建复杂系统所需要的。也正因为有这样的层次结构,我们才得以能够理解、描述、实现这些复杂系统。话说回来,我们似乎也只能理解那些有层次结构的系统。这也是为什么分层架构是软件设计中最基础,也是最重要的架构之一。

3.2 OCP

"Open to extend,Close to change"可以说是我们工程师的梦想,没有人愿意修改原来已经work的东西,因为修改就意味着要重新测试,就以为着可能引入新的bug,就以为着头发变少...... 大部分的设计模式都是为了OCP这个目标在努力。

我们平时提倡的immutable(不可变性)也是这个道理,immutable的String让我们可以放心使用,而不用考虑参数传递问题;immutable的函数式编程不用担心线程安全问题;immutable的docker image使得分层构建和复用成为可能;immutable infrastructure(不可变基础实施)提升了运维效率,是云原生的必要条件。

wrapper通过包装的形式,在保存原有功能的同时,通过扩展实现新增能力,从而保证了原有能力的immutable,完美的实现了OCP。此外,wrapper还可以通过基本组件的组合,可以实现非常复杂的业务逻辑。比如Spark通过RDD之间的组合来完成从简单到非常复杂的数据处理业务逻辑。


http://chatgpt.dhexx.cn/article/dgStl66i.shtml

相关文章

mybatis-plus中wrapper的用法(详细)

用到了wrapper,ge、le、ne、eq等的用法,及多表查询自写sql整理资料记录一下,以备后续复习。 目录------------(可点击相应目录直接跳转) 一、条件构造器关系介绍 条件构造器关系介绍 : wapper介绍 &…

锚点(anchorPoint)

转载请说明出处,谢谢。 原文出处:点击打开链接 今天研究了一下关于layer的anchorPoint问题。 附图: 原文出处:点击打开链接 位置坐标 position+anchorPoint(左下角0,0原点坐标系)。 要确…

cocos2d-x中的锚点(AnchorPoint)理解

锚点的定义 锚点是指节点在进行形状变换、位置变动时依据的基准点。可以想象为钉在墙上用于固定纸张的小图钉,或者公告栏上用于固定纸张用的围棋状的小磁粒。当对某个节点调用setPosition时,cocos2d-x即会将其锚点移动到相应位置;当对节点进行…

cocos2d-x3.2总结(一)Position和AnchorPoint的关系

当cocos2d-x引擎需要绘图时,就需要Position和AnchorPoint等属性。例如:在创建一个Sprite时,要设置Sprite的Position,而我们常常没有设置AnchorPoint,这是因为精灵的AnchorPoint默认值为(0.5,0.5&#xff09…

Anchor3

这里介绍如何修改 Anchor 的尺寸来提高小目标的检测效果,算法tricks优化小目标检测 修改 Anchor 尺寸 在实际的应用场景中,我们按照 MS COCO 标准中把大小不大于 32x32 或者占原始图片比率不足 0.01 的目标物体定义为一个小目标物体。 在使用 Anchor 的检测算法&…

ios-anchorPoint、position理解

anchorPoint(锚点)是layer的一个属性,下面我们来看看其对view的影响,本文主要通过图片方式展现: 锚点用单位坐标来描述也就是图层的相对坐标。在苹果文档中说明左下是(0,0),右上是(1,1),mac系统…

Anderson‘s pointer analysis

本文是垃圾文章,请直接学习其它资料 南京大学《软件分析》课程08(Pointer Analysis)https://www.cs.cmu.edu/~aldrich/courses/15-819O-13sp/resources/pointer.pdf 指针分析 指针分析是一类特殊的数据流问题,它是其它静态程序分析…

iOS围绕某点缩放或旋转的AnchorPoint的设定

经常会遇到需求,要求手势的缩放或者旋转操作,要求动作变化围绕某一个特定点,或者是两指的中心点,或者是某一个点。 这个问题首先要清晰的知道,iOS各个view的层次关系。特别是,要清除的知道,当前…

彻底理解CALayer的position与anchorPoint

引言 相信初接触到CALayer的人都会遇到以下几个问题: 为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与position有什么关系? 我也迷惑过,找过网上的教程,大部分都是复制粘…

position和anchorPoint

本人录制技术视频地址: https://edu.csdn.net/lecturer/1899 欢迎观看。 一、理论概述 1.简单介绍 CALayer有2个非常重要的属性:position和anchorPoint property CGPoint position; 用来设置CALayer在父层中的位置 以父层的左上角为原点(0, 0) prop…

Ant Design - Anchor

Anchor锚点 此组件的属性有以下几点: 现在给出一份例子 其他属性都很简单就不多说了,主要我遇到的麻烦是 getContainer 属性 锚点是默认body滚动的,所以如果你滚动的区域是body就会看到锚点的小蓝点是会随内容滚动的,但是如果你…

Anchor Point

On default, CCNode’s anchor point is (0, 0), which is at the left-bottom point. CCSprite’s anchor point is (0.5, 0.5), which is at the center. 如果你把一个CCSprite作为child加入到CCNode中,CCNode的anchor point不会对sprite的位置有影响,…

【Cocos2d-x 3.0学习笔记】 AnchorPoint 和Position 关系

先不多说,上两张图片: 解释一下上面图片的意思: 描点就是图片中红点的位置。setAnchorPoint的取值范围0~1,距离设置的是一张图片 setAnchorPoint(Point(0,0))表示在图片左下角, setAnchorPoint(Point(1,1))表示在图片…

iOS开发之layer.frame,layer.anchorPoint,layer.position对frame的影响

最近遇到相关的问题,所以就将这三个属性值,进行了分析和研究,话不多说,直接上代码了,详细的文字描述都在代码中,可以自行查看。 之前还写了一篇文章,也可以同时查看一下: iOS开发之…

anchorPoint

OS开发UI篇—CAlayer层的属性 一、position和anchorPoint 1.简单介绍 CALayer有2个非常重要的属性:position和anchorPoint property CGPoint position; 用来设置CALayer在父层中的位置 以父层的左上角为原点(0, 0) property CGPoint anchorPoint; 称为“定位点”、“…

iOS动画小课堂:定点缩放弹窗(利用锚点anchorPoint进行实现)包含完整demo

文章目录 前言I 基础知识 (CALayer)1.1 anchorPoint1.2 positionII iOS开发中常用的动画(定点缩放弹窗)2.1 核心代码2.2 完整demo源码see also前言 iOS开发中常用的动画(定点缩放弹窗)的应用场景: 会员详情的右侧下拉操作菜单 浏览器的右侧下拉菜单

UIView的bounds、frame、center/position、anchorPoint的关系

视图的frame,bounds和center属性仅仅是存取方法,当操纵视图的frame,实际上是在改变位于视图下方CALayer的frame,不能够独立于图层之外改变视图的frame。 对于视图或者图层来说,frame并不是一个非常清晰的属性&#xff…

彻底理解position与anchorPoint

原文 http://www.cnblogs.com/benbenzhu/p/3615516.html 引言 相信初接触到CALayer的人都会遇到以下几个问题: 为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与position有什么关系? 我也迷惑过&…

彻底弄清 anchorPoint 和 position

最近在研读《iOS Core Animation Advanced Techniques》这一本书,想系统地学习下关于 CALayer、Transition、以及动画等知识点。大家可以在 gitbook 上面找到该书的翻译版本。 传送门 在读到图层几何学这一章的时候,了解到了两个概念:anc…

Cocos2dx学习笔记9:cocos2dx锚点(Anchor Point)

锚点(AnchorPoint)是相对坐标,通常用来定义物体内部的点,在cocos2dx中,一般都是以加载精灵来实现游戏元素的表现,而精灵一般都是对应的一张图片资源。 我们在设置精灵位置的时候,要设置精灵中的锚点来和我们的坐标点相…