ABAP Strategy Design Pattern

Summary: in this tutorial, you will learn how to implement the ABAP strategy design pattern with a practical example.  

Problem

Sometimes when you enhance a report, a class, or an include, you have to pay a lot of effort and time to do regression tests in SAP. 

There is a case that when you change one part, other parts are broken. Oop! To avoid such situations, the application should be designed to follow a dominant object-oriented design known as the open-closed principle.

The program should be designed in the way that it is open for extension and closed for modification to eliminate the impact on existing logic. In the design pattern, you use the strategy pattern to design the application to follow this open-closed principle.

Intent

Define a family of algorithms, encapsulate each one, and make them interchangeable. The strategy pattern lets the algorithm vary independently from clients that use it.

Strategy Design Pattern UML Diagram

ABAP Strategy Design Pattern UML Diagram
ABAP Strategy Design Pattern UML Diagram

The classes and/or objects are participating in the strategy design pattern are:

  • Strategy
    • The strategy interface defines methods that represent common algorithms. The context uses the strategy interface to call the algorithms implemented by ConcreteStrategy.
  • ConcreteStrategy
    • implements the algorithm defined in the strategy interface.
  • Context
    • Context object contains a reference to a Strategy object. The context object delegates requests from the client to the strategy object.

ABAP Strategy Design Pattern Implementation

In ABAP programming, you often have to create an interface between the SAP system and non-SAP systems.

One of the most common uses interfaces is File. You can extract data from SAP to files in CSV or tab-delimited format. The file then can be downloaded into the local computer or put it to the file server for further processing by the non-SAP system.

We can use strategy design pattern to design our program as UML below:

ABAP Design Pattern UML
ABAP Design Pattern UML

Explanation of interfaces and classes in the diagram above:

  • IF_EXTRACTABLE is equivalent to Strategy
  • CLI_FILE_CLIENT, CL_FILE_SERVER are equivalent to ConcreteStrategy
  • CL_APP is equivalent to Context

Suppose in the future you have a new requirement to send the file via email to a distribution list, you just have to create another class called CL_FILE_EMAIL that implements the interface IF_EXTRACTABLE. Nothing needs to change except the logic handle email in the client. This is called the open-closed principle in object-oriented design. 

The Strategy design pattern supports “open for extension” but “closed for modification”. All the code for handling file extract to local computer and server are unchanged and therefore eliminating the effort for regression test on these parts.

Let’s take a look a the ABAP code implementation.

The Interface IF_EXTRACTABLE contains only one method called extract:

*----------------------------------------------------------------------*
*       INTERFACE if_extractable
*----------------------------------------------------------------------*
* ~ Strategy
*----------------------------------------------------------------------*
INTERFACE if_extractable.
  METHODS:
    extract.
ENDINTERFACE.                    "if_extractable

The CL_FILE_CLIENT and CL_FILE_SERVER classes implements IF_EXTRACTABLE interface:

*----------------------------------------------------------------------*
*       CLASS cl_file_client DEFINITION
*----------------------------------------------------------------------*
* ~ConcreteStrategy
*----------------------------------------------------------------------*
CLASS cl_file_client DEFINITION.
  PUBLIC SECTION.
    INTERFACES:
      if_extractable.
    ALIASES:
      extract FOR if_extractable~extract.
ENDCLASS.                    "cl_file_client DEFINITION

*----------------------------------------------------------------------*
*       CLASS cl_file_client IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS cl_file_client IMPLEMENTATION.
  METHOD extract.
    WRITE: 'Save file to the local PC'.
  ENDMETHOD.                    "extract
ENDCLASS.                    "cl_file_client IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS cl_file_server DEFINITION
*----------------------------------------------------------------------*
* ~ConcreteStrategy
*----------------------------------------------------------------------*
CLASS cl_file_server DEFINITION.
  PUBLIC SECTION.
    INTERFACES:
      if_extractable.
    ALIASES:
      extract FOR if_extractable~extract.
ENDCLASS.                    "cl_file_server DEFINITION

*----------------------------------------------------------------------*
*       CLASS cl_file_server IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS cl_file_server IMPLEMENTATION.
  METHOD extract.
    WRITE: 'Save file to the server'.
  ENDMETHOD.                    "extract
ENDCLASS.                    "cl_file_server IMPLEMENTATION

Next, implement Context class:

*----------------------------------------------------------------------*
*       CLASS cl_app DEFINITION
*----------------------------------------------------------------------*
* ~Context
*----------------------------------------------------------------------*
CLASS cl_app DEFINITION.
  PUBLIC SECTION.
    METHODS:
      constructor
        IMPORTING im_extractable
              TYPE REF TO if_extractable,
    process_output.
  PRIVATE SECTION.
    DATA:
       mo_extractable TYPE REF TO if_extractable.
ENDCLASS.                    "cl_app DEFINITION

*----------------------------------------------------------------------*
*       CLASS cl_app IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS cl_app IMPLEMENTATION.
  METHOD constructor.
    mo_extractable = im_extractable.
  ENDMETHOD.                    "constructor
  METHOD process_output.
    IF mo_extractable IS NOT INITIAL.
      mo_extractable->extract( ).
    ENDIF.
  ENDMETHOD.                    "process_output
ENDCLASS.                    "cl_app IMPLEMENTATION

Finally, develop a program to test our classes:

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: pa_local TYPE c RADIOBUTTON GROUP  pout,
            pa_servr  TYPE c RADIOBUTTON GROUP pout.
SELECTION-SCREEN END OF BLOCK b1.

DATA:
    go_app     TYPE REF TO cl_app,
    go_extract TYPE REF TO if_extractable.

START-OF-SELECTION.

  CASE  'X'.
    WHEN pa_local.
      CREATE OBJECT go_extract TYPE cl_file_client.
    WHEN pa_servr.
      CREATE OBJECT go_extract TYPE cl_file_server.
  ENDCASE.

  CREATE OBJECT go_app
    EXPORTING
      im_extractable = go_extract.
  go_app->process_output( ).
Strategy Design Pattern Program
Strategy Design Pattern Program
ABAP Strategy Design Pattern Program Output
ABAP Strategy Design Pattern Program Output

In this tutorial, you’ve learned how to implement the ABAP strategy design pattern that allows you to define a family of related algorithms, encapsulate each individual one, and make them interchangeable in terms of client uses.