What is the Iterator Design Pattern?
The Iterator Design Pattern is a behavioral pattern that provides a systematic way to access elements in a collection sequentially without exposing its underlying structure. In ABAP, this pattern helps navigate complex data structures like internal tables or custom objects efficiently.
Instead of directly accessing the internal structure, an iterator provides methods to retrieve elements one by one, ensuring encapsulation and maintainability.
Need for Iterator Design Pattern
When working with large datasets, direct access can lead to performance bottlenecks. Standard loops might not be flexible enough to manage complex collections. We often need a consistent way to access data across different collection types.
Advantages of Iterator Design Pattern
Encapsulation: Hides the internal structure of collections. Flexibility: Supports different traversal strategies (forward, backward, etc.). Maintainability: Changes to the collection’s structure do not affect how elements are accessed. Simplifies Navigation: Provides methods like has_next() and next() for seamless data retrieval.
Steps to Create an Iterator Design Pattern
1.Define the Data Model – Material Class
CLASS lcl_material DEFINITION.
PUBLIC SECTION.
METHODS: constructor IMPORTING im_matnr TYPE matnr.
DATA :lv_matnr TYPE matnr READ-ONLY.
ENDCLASS.
CLASS lcl_material IMPLEMENTATION.
METHOD constructor.
lv_matnr = im_matnr.
ENDMETHOD.
ENDCLASS.
2.The iterator interface (if_iterator) defines methods for navigating the collection.
INTERFACE if_iterator.
METHODS : has_next RETURNING VALUE(has_next) TYPE flag,
get_next RETURNING VALUE(object) TYPE REF TO object.
DATA : lo_collection TYPE REF TO if_collection,
v_current TYPE i,
v_step TYPE i.
ENDINTERFACE.
has_next() → Checks if there are more elements in the collection.
get_next() → Retrieves the next element in the collection.
lo_collection → Reference to the collection being iterated.
v_current → Tracks the current position in the collection.
v_step → Defines the increment step while iterating.
3.Define the Collection Interface
The collection interface (if_collection) defines methods for adding and retrieving elements.
INTERFACE if_collection.
METHODS : get_iterator RETURNING VALUE(iterator) TYPE REF TO if_iterator,
add IMPORTING element TYPE REF TO object,
get IMPORTING index TYPE i
RETURNING VALUE(object) TYPE REF TO object.
ENDINTERFACE.
4. Implement the Collection Class
The collection class (lcl_collection) stores materials and provides an iterator.
CLASS lcl_collection DEFINITION.
PUBLIC SECTION.
INTERFACES if_collection.
DATA : i_material TYPE STANDARD TABLE OF REF TO object.
ALIASES: get_iterator FOR if_collection~get_iterator,
add FOR if_collection~add,
get FOR if_collection~get.
ENDCLASS.
CLASS lcl_collection IMPLEMENTATION.
METHOD if_collection~get_iterator.
DATA(lo_iterator) = NEW lcl_iterator( io_collection = me ).
iterator = lo_iterator.
ENDMETHOD.
METHOD if_collection~add.
APPEND element TO i_material.
ENDMETHOD.
METHOD if_collection~get.
READ TABLE i_material INTO object INDEX index.
IF sy-subrc <> 0.
CLEAR object.
ENDIF.
ENDMETHOD.
ENDCLASS.
5.Implement the Iterator Class
The iterator class (lcl_iterator) provides methods to navigate the collection.
CLASS lcl_iterator DEFINITION.
PUBLIC SECTION.
INTERFACES if_iterator.
METHODS : constructor IMPORTING io_collection TYPE REF TO if_collection.
ALIASES: has_next FOR if_iterator~has_next.
PRIVATE SECTION.
ALIASES: lo_collection FOR if_iterator~lo_collection,
v_current FOR if_iterator~v_current,
v_step FOR if_iterator~v_step.
ENDCLASS.
CLASS lcl_iterator IMPLEMENTATION.
METHOD constructor.
lo_collection = io_collection.
v_step = 1.
v_current = 0.
ENDMETHOD.
METHOD if_iterator~has_next.
DATA obj TYPE REF TO object.
DATA idx TYPE i.
idx = v_current + v_step.
obj = lo_collection->get( idx ).
IF obj IS BOUND.
has_next = ‘X’.
ENDIF.
ENDMETHOD.
METHOD if_iterator~get_next.
v_current = v_current + v_step.
object = lo_collection->get( v_current ).
ENDMETHOD.
ENDCLASS.
6. Execute the Iterator in the Main Class
The main class (lcl_main) initializes the collection, adds elements, and iterates through them.
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS run.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD run.
DATA : lo_mcollection TYPE REF TO if_collection,
lo_miterator TYPE REF TO if_iterator,
lo_material TYPE REF TO lcl_material.
CREATE OBJECT lo_mcollection TYPE lcl_collection.
lo_miterator = lo_mcollection->get_iterator( ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT01’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT02’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT03’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT04’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT05’.
lo_mcollection->add( lo_material ).
WHILE lo_miterator->has_next( ) IS NOT INITIAL.
lo_material ?= lo_miterator->get_next( ).
WRITE: lo_material->lv_matnr.
ENDWHILE.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>run( ).
When to Go for the Iterator Design Pattern?
When dealing with complex data structures like nested internal tables. When a consistent way to traverse collections is required. When future-proofing code for potential changes in data structure. When simplifying access logic while maintaining data integrity.
Conclusion
The Iterator Design Pattern in ABAP provides a clean and structured way to traverse collections, improving maintainability and flexibility. By implementing iterators, developers can create reusable and efficient solutions for data access in SAP applications.
What is the Iterator Design Pattern? The Iterator Design Pattern is a behavioral pattern that provides a systematic way to access elements in a collection sequentially without exposing its underlying structure. In ABAP, this pattern helps navigate complex data structures like internal tables or custom objects efficiently. Instead of directly accessing the internal structure, an iterator provides methods to retrieve elements one by one, ensuring encapsulation and maintainability. Need for Iterator Design Pattern When working with large datasets, direct access can lead to performance bottlenecks. Standard loops might not be flexible enough to manage complex collections. We often need a consistent way to access data across different collection types. Advantages of Iterator Design Pattern Encapsulation: Hides the internal structure of collections. Flexibility: Supports different traversal strategies (forward, backward, etc.). Maintainability: Changes to the collection’s structure do not affect how elements are accessed. Simplifies Navigation: Provides methods like has_next() and next() for seamless data retrieval. Steps to Create an Iterator Design Pattern 1.Define the Data Model – Material Class CLASS lcl_material DEFINITION.
PUBLIC SECTION.
METHODS: constructor IMPORTING im_matnr TYPE matnr.
DATA :lv_matnr TYPE matnr READ-ONLY.
ENDCLASS.
CLASS lcl_material IMPLEMENTATION.
METHOD constructor.
lv_matnr = im_matnr.
ENDMETHOD.
ENDCLASS. 2.The iterator interface (if_iterator) defines methods for navigating the collection. INTERFACE if_iterator.
METHODS : has_next RETURNING VALUE(has_next) TYPE flag,
get_next RETURNING VALUE(object) TYPE REF TO object.
DATA : lo_collection TYPE REF TO if_collection,
v_current TYPE i,
v_step TYPE i.
ENDINTERFACE. has_next() → Checks if there are more elements in the collection. get_next() → Retrieves the next element in the collection. lo_collection → Reference to the collection being iterated. v_current → Tracks the current position in the collection. v_step → Defines the increment step while iterating. 3.Define the Collection Interface The collection interface (if_collection) defines methods for adding and retrieving elements. INTERFACE if_collection.
METHODS : get_iterator RETURNING VALUE(iterator) TYPE REF TO if_iterator,
add IMPORTING element TYPE REF TO object,
get IMPORTING index TYPE i
RETURNING VALUE(object) TYPE REF TO object.
ENDINTERFACE.
4. Implement the Collection Class The collection class (lcl_collection) stores materials and provides an iterator.CLASS lcl_collection DEFINITION.
PUBLIC SECTION.
INTERFACES if_collection.
DATA : i_material TYPE STANDARD TABLE OF REF TO object.
ALIASES: get_iterator FOR if_collection~get_iterator,
add FOR if_collection~add,
get FOR if_collection~get.
ENDCLASS.
CLASS lcl_collection IMPLEMENTATION.
METHOD if_collection~get_iterator.
DATA(lo_iterator) = NEW lcl_iterator( io_collection = me ).
iterator = lo_iterator.
ENDMETHOD.
METHOD if_collection~add.
APPEND element TO i_material.
ENDMETHOD.
METHOD if_collection~get.
READ TABLE i_material INTO object INDEX index.
IF sy-subrc <> 0.
CLEAR object.
ENDIF.
ENDMETHOD.
ENDCLASS. 5.Implement the Iterator Class The iterator class (lcl_iterator) provides methods to navigate the collection. CLASS lcl_iterator DEFINITION.
PUBLIC SECTION.
INTERFACES if_iterator.
METHODS : constructor IMPORTING io_collection TYPE REF TO if_collection.
ALIASES: has_next FOR if_iterator~has_next.
PRIVATE SECTION.
ALIASES: lo_collection FOR if_iterator~lo_collection,
v_current FOR if_iterator~v_current,
v_step FOR if_iterator~v_step.
ENDCLASS.
CLASS lcl_iterator IMPLEMENTATION.
METHOD constructor.
lo_collection = io_collection.
v_step = 1.
v_current = 0.
ENDMETHOD.
METHOD if_iterator~has_next.
DATA obj TYPE REF TO object.
DATA idx TYPE i.
idx = v_current + v_step.
obj = lo_collection->get( idx ).
IF obj IS BOUND.
has_next = ‘X’.
ENDIF.
ENDMETHOD.
METHOD if_iterator~get_next.
v_current = v_current + v_step.
object = lo_collection->get( v_current ).
ENDMETHOD.
ENDCLASS. 6. Execute the Iterator in the Main Class The main class (lcl_main) initializes the collection, adds elements, and iterates through them. CLASS lcl_main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS run.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD run.
DATA : lo_mcollection TYPE REF TO if_collection,
lo_miterator TYPE REF TO if_iterator,
lo_material TYPE REF TO lcl_material.
CREATE OBJECT lo_mcollection TYPE lcl_collection.
lo_miterator = lo_mcollection->get_iterator( ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT01’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT02’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT03’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT04’.
lo_mcollection->add( lo_material ).
CREATE OBJECT lo_material
EXPORTING
im_matnr = ‘MAT05’.
lo_mcollection->add( lo_material ).
WHILE lo_miterator->has_next( ) IS NOT INITIAL.
lo_material ?= lo_miterator->get_next( ).
WRITE: lo_material->lv_matnr.
ENDWHILE.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>run( ). When to Go for the Iterator Design Pattern? When dealing with complex data structures like nested internal tables. When a consistent way to traverse collections is required. When future-proofing code for potential changes in data structure. When simplifying access logic while maintaining data integrity. Conclusion The Iterator Design Pattern in ABAP provides a clean and structured way to traverse collections, improving maintainability and flexibility. By implementing iterators, developers can create reusable and efficient solutions for data access in SAP applications. Read More Application Development and Automation Blog Posts articles
#SAP