关于 ABAP 单例设计模式的一个冷门知识点

简介: 关于 ABAP 单例设计模式的一个冷门知识点

单例模式(Singleton)是设计模式里实现起来最简单,使用最普遍的一种。

单例模式确保了一个类在任意时刻只有一个实例存在,同时提供了一个全局访问点来获取这个实例。在单例模式的使用场合下,确保某个类在整个系统中只有一个实例非常重要,比如配置管理器、线程池、缓存或者日志对象等。使用单例模式可以避免由于多个实例造成的资源使用冲突,或是数据不一致的问题。

单例模式按照唯一的实例创建时间点的不同,可以分为 LazyEager 两种变体,有的文档里又称为懒汉式单例模式饿汉式单例模式

使用 ABAP 编程时,当对象实例在全局访问点里被请求时,才创建实例的实现方式,称为 Lazy 单例模式。

在 CLASS_CONSTRUCTOR 里创建实例的实现方式,称为 Eager 单例模式。

在 ABAP 里实现 Eager 型单例模式比较简单,新建一个类,将 Instance Generation 设置成 Private

然后定义一个 Static 属性 so_instance, 用来维护该类唯一的一个实例:

将类的构造函数设置成 Private:

在该构造函数里,随便打印一些内容:

method CONSTRUCTOR.
    WRITE:/ 'do some initialization work'.
endmethod.

在 CLASS_CONSTRUCTOR 里完成唯一实例的初始化工作。

method CLASS_CONSTRUCTOR.
    CREATE OBJECT SO_INSTANCE.
  endmethod.

然后在全局访问点,GET_INSTANCE 方法里,返回之前在 CLASS_CONSTRUCTOR 里创建好的唯一实例。

该单例的消费者,在任意时间点,都只能通过 GET_INSTANCE 方法,获得唯一的对象实例。在该类的实现体外,企图使用 CREATE OBJECT 额外创建一个新的对象实例,会遇到语法错误:

An instance of the class cannot be created outside the class.

到此为止,都是大家非常熟悉的内容。

有没有一种办法,能够在 ZCL_PRIVATE_TEST 类的外部,再得到另一个不同的对象实例呢?如果可以的话,从某种程度上说,ABAP 的单例模式,就已经被破坏了。

技术上来说,确实有一种办法,即先把 GET_INSTANCE 返回的实例序列化成 XML 字符串,然后再把这个 XML 字符串,反序列化成对象实例。反序列化后得到的新对象实例,和原始的实例相比,已经是两个不同的对象实例了

当然为了让一个类能够被序列化,在 ABAP 里,需要给它添加一个接口 IF_SERIALIZABLE_OBJECT. 这个接口不包含任何方法,也称为 Tag Interface,唯一的作用,就是告诉 ABAP 框架,这个类需要支持 ABAP 的序列化和反序列化。

ABAP 无法像 Java 和 TypeScript 这些编程语言一样,从语言层面支持注解(Annotations)特性,所以只有用 Tag Interface 来实现同样的目的,即给类提供额外的标注信息,这些标准信息仅供框架解析和使用,不会对应用程序的执行造成任何影响。

看下面这段代码。第三行到第五行,声明了类的三个实例,其中实例 1 和实例 2,都是通过 GET_INSTANCE 返回的,因此这两个实例完全相同,所以第 13 行的打印语句,lo_instance1 = lo_instance2 表达式的布尔值计算结果,为 abap_true.

并且我们注意到类的 CONSTRUCTOR 构造函数里的打印语句,只执行了一次,说明在整个过程中,类的实例化过程,只发生了一次。

再继续往下看代码,第 17 行,实例1 被序列化成 XML 字符串,存储在变量 s 里。

代码第 19 行,XML 字符串 s 又被反序列化,还原成了实例 3.

此时实例 3 和实例 1 已经是完全不同的两个实例了,所以 lo_instance1 = lo_instance3 的表达式布尔值计算结果,为 abap_false.

这个行为也能在下图的 ABAP 调试器里清楚地观察到:在 ABAP 调试器里,实例1 和实例 2 的 id 相同,都是 10,而实例 3 的编号为 11.

本文介绍了 ABAP 单例模式中一个不为人熟知的知识点:可序列化 Tag 接口 IF_SERIALIZABLE_OBJECT,算是给 ABAP 单例模式的实现,开了一个口子。然而避免踏入这个坑的措施也很简单,只要一个 ABAP 类没有被赋予 IF_SERIALIZABLE_OBJECT 接口,就不会出现本文描述的这种单例行为被破坏的问题。

相关文章
|
1月前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
61 0
|
1月前
|
设计模式 缓存 安全
单例设计模式的优缺点
单例设计模式的优缺点
32 0
|
1月前
|
设计模式 安全 Java
【设计模式】2、设计模式分类和单例设计模式
【设计模式】2、设计模式分类和单例设计模式
25 0
|
1月前
|
设计模式 Java
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
28 2
|
3月前
|
设计模式 消息中间件 安全
多线程编程设计模式(单例,阻塞队列,定时器,线程池)(二)
多线程编程设计模式(单例,阻塞队列,定时器,线程池)(二)
34 1
|
3月前
|
设计模式 安全 Java
最简单的设计模式是单例?
单例模式可以说是Java中最简单的设计模式,但同时也是技术面试中频率极高的面试题。因为它不仅涉及到设计模式,还包括了关于线程安全、内存模型、类加载等机制。所以说它是最简单的吗?
56 3
最简单的设计模式是单例?
|
28天前
|
设计模式 安全 Java
在Java中即指单例设计模式
在Java中即指单例设计模式
18 0
|
5月前
|
设计模式 存储
static应用之 单例设计模式(饿汉单例&懒汉单例)
本章我们来学习单例模式中的饿汉单例和懒汉单例,那么什么是单例模式呢?应用该模式的这个类永远只有一个实列,即一个类只能创建一个对象例如电脑上的任务管理器对象只需要一个就能解决问题,可以节省内存空间先定义一个类,把构造器私有如下图,先来看一下没有把构造器私有化的SingleInstance类,此时Test类中可以随意创建多个SingleInstance的实例化。 在SingleInstance类中用private修饰无参构造器,此时左边new方法报错了。我们在右边创建一个静态变量来存储对象,变量名为instan
24 0
|
6月前
|
设计模式 安全 Java
【设计模式】单例设计模式
1、前言 单例模式是一种设计模式,它确保一个类只能创建一个实例,并提供一种全局访问这个实例的方式。在Java中,单例模式可以通过多种方式来实现,其中最常见的是使用私有构造函数和静态方法实现
33 0
|
3月前
|
设计模式 缓存 安全
Go语言必学的单例设计模式
Go语言必学的单例设计模式
34 0