关于 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 接口,就不会出现本文描述的这种单例行为被破坏的问题。

相关文章
|
6月前
|
设计模式
单例设计模式步骤
单例设计模式步骤
33 1
|
6月前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
135 0
|
6月前
|
设计模式 缓存 安全
单例设计模式的优缺点
单例设计模式的优缺点
|
6月前
|
设计模式 安全 Java
【设计模式】2、设计模式分类和单例设计模式
【设计模式】2、设计模式分类和单例设计模式
57 0
|
6月前
|
设计模式 Java
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
51 2
|
6月前
|
设计模式 安全 Java
在Java中即指单例设计模式
在Java中即指单例设计模式
39 0
|
2月前
|
设计模式 存储 安全
设计模式——设计模式介绍和单例设计模式
饿汉式(静态常量)、饿汉式(静态代码块)、懒汉式(线程不安全)、懒汉式(线程安全,同步方法)、懒汉式(线程不安全,同步代码块)、双重检查(推荐,线程安全、懒加载)、静态内部类(推荐)、枚举(推荐)
设计模式——设计模式介绍和单例设计模式
|
3月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
47 1
|
6月前
|
设计模式 安全 Java
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
|
3月前
|
设计模式 Java
【Java】单例设计模式
【Java】单例设计模式