SAP ABAP 里存在 Java List 这种集合工具类么?CL_OBJECT_COLLECTION 了解一下
Jerry 以前在工作中交替做着 ABAP 和 Java 开发时,总是在使用一种语言时,怀念另一种语言的便利之处,比如用 ABAP 开发时,怀念 Java 里以 List 为代表的功能强大,使用方便的集合工具类。
List 或许是众多 Java 初学者最先接触和掌握的 Java 集合工具接口之一。以最具代表性的实现类 ArrayList 为例,查看其源代码,发现 ArrayList 不过就是用面向对象的编程方式封装了对一个对象数组的常用操作,使其不仅支持 Java 原生 Array 的所有功能,同时也支持前者不具备的动态扩容功能。
对 Java 稍有了解的开发者,要自己仿照着写出一个同样的 ArrayList 实现,并不是一件困难的事情。不过 List 接口和其众多实现类都是 Java 开发包的一部分,这使得 Java 开发者做应用开发时不用重复造轮子,可以直接使用,非常方便。
那么 SAP ABAP 里存在类似的集合工具类么?
首先我们有内表,具备 Java Array 的所有功能,并且功能和使用灵活度上来说都远胜后者。但内表的操作毕竟是一种面向过程的编程思路。ABAP 里存在类似 Java List 的接口吗?
通过之前查看 Java ArrayList 的实现源代码,我们可以仿照其思路,在 ABAP 里实现一个一模一样的 ABAP ArrayList 出来,只需要定义一个行类型(Table Line)为对象引用的内表变量,再用面向对象编程方式实现对这个内表变量插入,删除,和按索引访问的功能即可。而 Java ArrayList 的动态扩容,ABAP 内表原生就支持。
事实上 SAP CRM 就采取了这种实现思路,CL_CRM_BOL_ENTITY_COL,这个工具类,从名称上就能判断出它是 BOL 实例的存储容器,提供了容器内 BOL 实例元素的插入,删除和遍历的功能。
然而这个列表只能插入类型为 BOL 实例的元素,有更通用的 ABAP List 工具类么?那就是 CL_OBJECT_COLLECTION, 提供了类似 Java ArrayList 对列表元素的基本操作:
插入
删除
按索引访问
遍历
清空列表
这个工具类内部维护的内表类型为 TYPE STANDARD TABLE OF REF TO OBJECT, 因此可插入指向任何对象实例的引用。
Jerry 这篇博客曾经介绍过该工具类的一个使用例子:
CL_OBJECT_COLLECTION, iterator and Polymorphism
假设我们要开发一个计算图形面积的应用,支持圆形和长方形。实现两个类 ZCL_CIRCLE 和 ZCL_RECTANGLE, 分别按照圆形和长方形的面积计算公式,实现 GET_AREA 方法。
传统的实现方式
定义一个 Table Line 类型为通用的对象引用(TYPE REF TO OBJECT)的内表 lt_shape,用于存放圆形和长方形的实例对象引用。
每次创建圆形或者长方形的对象实例之后,添加到内表中,然后 LOOP 内表,逐行取出元素,用 IS INSTANCE OF 关键字,判断当前记录指向的是圆形还是长方形实例,再用 CAST 进行强制类型转换,调用对应的面积计算方法。
这种实现方式,在 LOOP 里有 IF ELSE 判断,IS INSTANCE OF 和 CAST 这三种非常丑陋的写法。将来如果要支持其他图形比如三角形的面积计算,又得在 LOOP 里添加新的 ELSE 分支,这违反了程序设计的开闭原则-对扩展开放,对修改封闭。
采用 CL_OBJECT_COLLECTION 的多态实现
定义一个新的接口 ZIF_SHAPE,圆形和长方形的类均实现自这个接口:
借助 CL_OBJECT_COLLECTION, 采取面向对象编程里多态(Polymorphism)的思路,我们不仅避免了丑陋的 IF-ELSE,繁琐的类型探测 IS INSTANCEOF 和强制类型转换 CAST,同时将代码行数从 37 行减少到了 20 行。将来要是得增加对其他图形的支持,只需要新建图形类并实现,而无需修改下面的计算逻辑。
当然这个例子如果不用 CL_OBJECT_COLLECTION, 而是每次把实现了 ZIF_SHAPE 接口的图形类实例,加入到 TABLE LINE 类型为 TYPE REF TO OBJECT 的内表里,然后直接 LOOP 内表,也可以达到同样的效果。本文只是为了演示 CL_OBJECT_COLLECTION 的用法,故而没有使用内表来完成计算。
本例实际上是迭代器设计模式的一个具体应用。迭代器设计模式是提供一种访问底层对象集合而不暴露底层表示的方法。Iterator 将访问对象集合的逻辑从 collection 对象本身解耦。这种解耦在遍历不同类型的集合对象时提供了额外的优势。
Iterator 还提供了根据需求以不同方式遍历集合的灵活性。如果我们将 position 嵌入到 Collection 对象本身中,它将不允许我们以不同的方式实现多重访问。迭代器从 Collection 对象中获取访问的责任,并将其放在自己内部。迭代器提供了访问底层数据结构的唯一接口。客户端不需要知道正在访问的集合对象的类型。
希望本文能帮助大家通过 ABAP 工具类 CL_OBJECT_COLLECTION 实现迭代器设计模式的做法有一个最基础的了解。
感谢阅读。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/07029284ba4efa01b2c5e7ff1】。文章转载请联系作者。
评论