Behavioral patterns concentrate on interaction by showing how objects exchange information, distribute tasks, and execute sophisticated logic as part of a unified operation.
The system's dynamic elements receive attention from behavioral patterns, creational patterns handle object creation, and structural patterns manage object arrangement. These patterns help you structure algorithms and distribute work and state management, which results in flexible and maintainable programs that you can easily expand.
Some common behavioral patterns you may encounter when developing with ABAP include the following.
The chain of responsibility pattern passes a request along a chain of handlers until one of the handlers processes it. In ABAP, this could be applied to validation logic with multiple classes of check conditions (such as authorizations, data integrity, and business rules) until one handler either handles the request or fails it.
The command pattern encapsulates a request as an object, allowing you to parameterize clients and queue, log, or undo actions. In ABAP, this is useful for workflow tasks or background jobs, where each command object represents a unit of work that can be executed or rolled back.
The interpreter pattern defines grammar and interprets sentences in that grammar. While not as common in day-to-day ABAP, it can be used for parsing simple business rules, formulas, or domain-specific query languages stored in Customizing tables.
The iterator pattern provides a way to access elements of a collection sequentially without exposing the underlying representation. In ABAP, custom iterator classes can walk over internal tables, selection results, or even BAPI return sets, giving consumers a clean interface to consume data row by row.
The mediator pattern centralizes complex communication between objects, ensuring they don’t need to reference each other directly. ABAP apps that coordinate multiple UI controls or modular services can benefit from a mediator that routes messages through a single hub.
The memento pattern captures and restores an object’s internal state without exposing its internals. In ABAP, this can be useful when you’re implementing the undo functionality for user transactions or when you’re saving and restoring a complex object’s state during batch processing.
The observer pattern defines a one-to-many dependency so that when one object changes state, all dependents are notified. ABAP supports this pattern naturally through class events and event handlers, making it a go-to for scenarios where multiple consumers react to a single source of truth.
The state pattern allows an object to alter its behavior when its internal state changes. In ABAP, you might model a sales order lifecycle (i.e., created, released, blocked, and billed) as a set of state objects, each controlling which actions are possible.
The strategy pattern defines a family of algorithms and lets you swap them at runtime. This is a natural fit in ABAP when you want to choose between multiple pricing, tax, or calculation strategies, depending on the customization or context.
The template method pattern defines the skeleton of an algorithm in a base class, allowing subclasses to redefine certain steps. SAP frameworks use this extensively, and ABAP developers can apply it in scenarios like invoice processing where the general process is fixed but specific steps vary by document type.
The visitor pattern lets you define new operations on an object structure without changing the objects themselves. Though less common in ABAP, it can be useful in hierarchical structures (such as BOMs or organizational charts), where you want to apply different operations—such as validation, reporting, and transformation—without cluttering the objects with every possible behavior.
We’ll explain how you can use behavior patterns in more detail in the following sections, including a closer look at the strategy pattern.
Behavioral patterns help developers separate the functional aspects of their code from the implementation details. They enable you to create reusable behavior blocks that enable request delegation between multiple handlers, event broadcasting to subscribers, and algorithm replacement. These patterns match the natural features of ABAP language through its implementation of class events, exception handling, and interface-based programming.
ABAP systems that operate for decades with complex business logic benefit from behavioral patterns because these patterns transform complicated IF statement tangles into adaptable designs. SAP’s frameworks implement various patterns through workflow engines (command and chain of responsibility), UI event handling (observer and mediator), and app frameworks that provide business process templates (template method). Recognizing these patterns will help you improve your ABAP skills, and you’ll be able to better understand and analyze standard SAP code.
The strategy pattern enables clients to select algorithms from a common interface family at runtime. You avoid distributed IF … ELSEIF … branches for calculation selection in the system by moving this decision to the construction or configuration phase, and the rest of the system is free to use the interface. The selection of tax, pricing, and/or rounding rules matches perfectly with Customizing because users make selections based on company code, country, document type, or feature toggle. The strategy pattern maintains explicit choices that remain testable and replaceable.
The calculation of sales item taxes requires careful attention. The requirements differ across countries and sometimes across product groups. The system requires each algorithm to operate independently, but the caller needs to interact with tax strategy without knowing which algorithm runs because the caller only needs to request tax computation for a specific item.
Let’s look at an example strategy pattern. First, you’ll define the strategy interface—one small, intention-revealing contract.
INTERFACE zif_tax_strategy PUBLIC.
METHODS compute_tax
IMPORTING is_itemTYPE zty_so_item " your domain type
RETURNING VALUE(rv_tax) TYPE decfloat34
RAISING cx_static_check.
ENDINTERFACE.
Next, provide a few concrete strategies, as shown in the listing below Keep each focused on its rule set. For example, we created a US tax strategy that only holds logic related to US-based taxes. We also created a class for an EU tax strategy that only holds logic related to European tax strategies.
CLASS zcl_tax_strategy_us DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES zif_tax_strategy.
ENDCLASS.
CLASS zcl_tax_strategy_us IMPLEMENTATION.
METHOD zif_tax_strategy~compute_tax.
" Simplified: destination-based, flat rate example
rv_tax = is_item-net_amount * CONV decfloat34( '0.060' ).
ENDMETHOD.
ENDCLASS.
CLASS zcl_tax_strategy_eu DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES zif_tax_strategy.
ENDCLASS.
CLASS zcl_tax_strategy_eu IMPLEMENTATION.
METHOD zif_tax_strategy~compute_tax.
" Simplified: VAT based on material group
DATA(lv_rate) = COND decfloat34(
WHEN is_item-matkl = 'FOOD' THEN '0.04'
WHEN is_item-matkl = 'BOOK' THEN '0.07'
ELSE '0.20' ).
rv_tax = is_item-net_amount * lv_rate.
ENDMETHOD.
ENDCLASS.
A small context object uses the strategy pattern. It doesn’t know (or care) which strategy it got. Our example below shows the implementation of a tax calculator. The purpose of the class is to just calculate the taxes for an item. It shouldn’t have to know which country it’s calculating taxes for or the different types of strategies there are to calculate taxes. It just needs to know that it has an item and it needs to calculate tax—that should be its sole purpose.
CLASS zcl_tax_calculator DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
METHODS constructor IMPORTING io_strategy TYPE REF TO zif_tax_strategy.
METHODS tax_for_item
IMPORTING is_item TYPE zty_so_item
RETURNING VALUE(rv_tax) TYPE decfloat34
RAISING cx_static_check.
PRIVATE SECTION.
DATA mo_strategy TYPE REF TO zif_tax_strategy.
ENDCLASS.
CLASS zcl_tax_calculator IMPLEMENTATION.
METHOD constructor.
mo_strategy = io_strategy.
ENDMETHOD.
METHOD tax_for_item.
rv_tax = mo_strategy->compute_tax( is_item = is_item ).
ENDMETHOD.
ENDCLASS.
Finally, wire it up. A strategy can be determined via Customizing, feature flags, or a factory class. Our example below shows the strategy being determined by a factory class, where we pass in the country code and that determines which tax strategy is instantiated to be used within the tax calculator.
CLASS zcl_tax_strategy_factory DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS for_context
IMPORTING iv_country TYPE land1
RETURNING VALUE(ro_strategy) TYPE REF TO zif_tax_strategy.
ENDCLASS.
CLASS zcl_tax_strategy_factory IMPLEMENTATION.
METHOD for_context.
CASE iv_country.
WHEN 'US'. ro_strategy = NEW zcl_tax_strategy_us( ).
WHEN 'DE'
OR 'FR'
OR 'ES'. ro_strategy = NEW zcl_tax_strategy_eu( ).
WHEN OTHERS.
RAISE EXCEPTION TYPE cx_static_check
EXPORTING textid = cx_static_check=>default_textid. "handle gracefully
ENDCASE.
ENDMETHOD.
ENDCLASS.
Below shows the usage of this strategy with the tax calculator.
DATA(lo_strategy) = zcl_tax_strategy_factory=>for_context( iv_country = 'US').
DATA(lo_calculator) = NEW zcl_tax_calculator( lo_strategy ).
DATA(lv_tax) = lo_calculator->tax_for_item( is_item = ls_item ).
The solution remains maintainable because each new rule introduction allows developers to create new classes that extend the factory class without impacting existing strategies. ABAP Unit tests can create fake strategies for scenario simulation, while you can test each strategy rule independently. Domain code becomes more readable by including a straightforward method named compute_tax instead of implementing various country and product type branches.
Keep in mind the following when using strategy patterns:
The strategy pattern exists throughout ABAP apps, including tax calculations, pricinglogic, rounding functions, number assignment, currency conversion, discount calculation, and serialization through shared interface encoding methods. Any situation requiring a CASE statement to select an algorithm should implement the strategy pattern.
Behavioral patterns establish standardized interaction rules between objects. These patterns define how objects communicate and work together, while creational patterns determine object creation methods and structural patterns determine object assembly methods. ABAP developers can use these patterns to create isolated algorithms and delegated responsibilities and runtime condition changes. The strategy pattern provides a successful implementation that enables runtime logic switching without requiring any modifications to existing calling code. The observer pattern, along with template method and command pattern, share similar design principles because they provide extensible solutions to manage complex logic in a clean manner.
Ready to level up your ABAP skills? Explore the full range of our ABAP-focused online courses, from foundational programming to advanced RAP, CDS, AMDP, unit testing, and more. Each one is instructor-led (live and on-demand), includes recordings and slide decks, and is designed to give you practical take-away skills you can apply right away in your SAP landscape. Click on the banner below to get started!
Editor’s note: This post has been adapted from sections of the books Object-Oriented Programming with ABAP Objects by Jeffrey Boggess, Colby Hemond, James Wood, and Joseph Rupert. Jeffrey is an enterprise integration specialist at Bowdark Consulting focused on building seamless integrations between SAP, Azure, and Dataverse to solve complex business challenges and provide dependable solutions for clients. Colby is a senior technical consultant at Bowdark Consulting, where he is dedicated to bringing innovative ideas and solutions to clients and supporting them in their digital transformation. James is the founder and CEO of Bowdark Consulting, Inc., a consulting firm specializing in technology and custom development in the SAP landscape. Joseph is a senior data architect at Bowdark Consulting, Inc. with expertise in migrating complex SAP landscapes to cloud platforms, enabling scalable, secure, and high-performance data ecosystems.
This post was originally published 6/2026.