Singleton Pattern in ABAP: Useful Tool or Interview Trap?
Practical Examples & Testing
The Singleton is probably the most frequently mentioned design pattern in ABAP interviews.
Not because it is the most important or the most widely used pattern in real-life systems - but because it touches the core ideas of object-oriented programming: controlled instantiation, encapsulation, and responsibility.

Knowing Singleton is often treated as a proxy for “knowing OOP and design patterns in general”.
I don’t fully agree with that assumption - but there is a reason why this pattern keeps coming up.
At the same time, Singleton is one of the most incorrectly implemented patterns in ABAP codebases.
Either it is implemented in a way that breaks testability, or it is used where it shouldn’t be used at all.
This post explains what problem Singleton actually solves in ABAP, when it makes sense, and where its limits are.
Purpose
The purpose of the Singleton pattern is simple:
Ensure that exactly one instance of a class exists and provide a global access point to it.
This is not about convenience. It is about consistency of state during a runtime session.
Why Singleton Is Common in ABAP
ABAP systems naturally encourage certain Singleton-like scenarios:
  • long-living internal sessions
  • framework-driven execution (enhancements, exits, determinations)
  • shared runtime context
  • expensive or repetitive database access
Typical ABAP use cases include:
Configuration readers - customizing or configuration loaded once and reused
Buffers / caches - data calculated once and reused during the same runtime
Shared system services - message collectors, protocol writers, runtime context holders
Implementation
A correct Singleton implementation in ABAP relies on:
  1. A public static factory method (get_instance)
  2. Controlled instantiation via CREATE PRIVATE
  3. A private static attribute holding the instance reference
CLASS zcl_app_buffer DEFINITION
  PUBLIC
  CREATE PRIVATE.

  PUBLIC SECTION.
    INTERFACES: zif_app_buffer.
    ALIASES: add_message FOR zif_app_buffer~add_message,
             get_buffer FOR zif_app_buffer~get_buffer.
    METHODS: constructor.
    CLASS-METHODS get_instance
      RETURNING
        VALUE(ro_instance) TYPE REF TO zif_app_buffer.
  PROTECTED SECTION.

  PRIVATE SECTION.
    CLASS-DATA mo_instance TYPE REF TO zcl_app_buffer.
    "some other logic
    DATA: mt_buffer TYPE z_singleton_string_table.
ENDCLASS.

CLASS zcl_app_buffer IMPLEMENTATION.
  METHOD constructor.
    "if some complicated logic is needed
  ENDMETHOD.

  METHOD get_instance.
    mo_instance = COND #( WHEN mo_instance IS BOUND
                          THEN mo_instance
                          ELSE NEW #( ) ).

    RETURN mo_instance.
  ENDMETHOD.

  METHOD add_message.
    mt_buffer = VALUE #( BASE mt_buffer ( iv_message ) ).
  ENDMETHOD.

  METHOD get_buffer.
    RETURN mt_buffer.
  ENDMETHOD.
ENDCLASS.
Why the Constructor Is Public (Global Class Case)
This is a common ABAP pitfall.
  1. Object creation is restricted via CREATE PRIVATE1
  2. The constructor itself must remain public
Why?
The explanation from the SAP Help:
Using Singleton in ABAP Reports
There is one additional usage that deserves special attention: Singleton as a local application class in an ABAP report.
This is a widely accepted and commonly recommended practice when you want to apply object-oriented design inside a procedural container like a report.
Why This Is Considered AcceptableUsing a local Singleton (often named lcl_application) helps to:
Control lifecycle - Ensure the report logic is executed only once per internal session (usually via a static entry method like RUN)
Encapsulate runtime state - Calculated values, flags, or message containers stay consistent
Provide a clean entry point - Procedural top-level code, object-oriented core logic
Improve structure and maintainability - Compared to large procedural reports
Example of the simple basic version of such application you can see here Singleton report
Testing
Testing the Singleton Itself
The Singleton can be verified via its public methods.
A FRIENDS relationship with the test class is not required.
Check implementation in Singleton test class
The test validates that:
→ multiple calls to get_instance return the same object
→ state changes are shared across calls
Mocking Singleton as a Dependency
The real challenge starts when a Singleton is used inside other classes.
Best practice:
→ expose behavior via an interface
→ mock the interface
→ inject it into the Code Under Test
This avoids coupling tests to global state.
Check implementation in Singleton dependency injection
This approach ensures:
→ complete test isolation
→ predictable results
→ no dependency on runtime order
Another way to inject Singleton as a dependency - is to use Local friends and store the instance in private attribute.
When Dependency Injection Becomes a Problem
In real projects, a class may depend on:
→ configuration readers
→ repositories
→ loggers
→ helper services
→ technical utilities
If all dependencies are injected explicitly:
→ constructors and method signatures grow quickly
→ the caller must be aware of many technical details
→ usage becomes cumbersome and error-prone
→ the public API exposes internal implementation concerns
This violates an important principle:
Consumers should depend on behavior, not on wiring details. That is why in such cases the better solution is to create an instance inside and store it as an attribute (for future testing).
Check implementation in Singleton with local friend
Final Thoughts
Singleton is overrepresented in interviews and often misunderstood in practice.
→ It is not the most important pattern you will use
→ It does not define your OOP expertise
→ It does solve real problems - when used intentionally
Use Singleton when:
→ exactly one instance is a real requirement
→ runtime state consistency matters
→ lifecycle is clearly defined
Avoid it when:
→ dependency injection alone is sufficient
→ global state becomes a shortcut
Made on
Tilda