ABAP Objects Design Patterns – Iterator

By | January 23, 2012 | ABAP Objects, OO Design Patterns | 8,344 | 5

Check out the Iterator design pattern implementation in ABAP Objects – another behavioral design pattern.

What is an Iterator ?

Iterator design pattern is to provide a way to access the underlying object collection without exposing the underlying representations. Iterator decouples the logic to access the collection of objects out of the Collection object itselft. This decoupling provides added adavantage while traversing through the different type of collection objects.

Iterator also provides the flexibilty to traverse the collection in different ways based on the requirement. If we have position embeded within the Collection object itself, it wont allow us to achieve the multiple access in different ways. The iterator takes the responsibility for access out of the Collection object and put that within itself. The iterator provides a unique interface to access the underlying datastructure. Clients doesn’t need to know what type of collection object is being accessed.

Standard Classes – But not useful

Standard SAP has provided the classes, CL_OBJECT_COLLECTION for Object collection and CL_OBJECT_COLLECTION_ITERATOR for Iterator. The underlying interfaces are not generic enough for handing other type of collection options.
The biggest drawback of using these classes is:

  • Method GET_ITERATOR only returns the object type referrence to CL_OBJECT_COLLECTION_ITERATOR. This method should actually return the object type IF_OBJECT_COLLECTION_ITERATOR.
  • Implementation of REMOVE method in class CL_OBJECT_COLLECTION is not efficient
  • Required methods are not part of the interface like ADD, REMOVE etc.

So for this demo application, I would create similar interfaces and implementing classes which are more generic and can be used in different collection and iterator implementation.

UML

Lets check out this UML used for the demo application.

UML of Iterator Design Pattern in ABAP

Components used in this UML:

  • IF_ITERATOR – This provides the interface to access and traverse through the list. This component is an Iterator. This object would have different methods to access the list in different manners.
  • LCL_ITERATOR – This Concrete Iterator implements the interface IF_ITERATOR. This object contains all the logic for list access.
  • IF_COLLECTION – This object has method to instantiate the iterator objects. This is also referred as Aggregate. This interface contains all the methods for List manipulation like ADD, REMOVE, GET etc.
  • LCL_COLLECTION – Implements the interface IF_COLLECTION as a Concrete Aggregate. This object would have a logic to instantiate proper iterator object. This object would also implements the list operation methods. Iterator would use methods e.g. GET to access particular object from the list.

Code Lines

Lets checkout the Code lines on how to implement the Iterator Design Patterns using ABAP. Best way to understand this example is to implement the code in SAP and debugging it through.

Iterator Design Pattern Demo

 
REPORT znp_dp_iterator.
*
CLASS lcl_item DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor IMPORTING iv_name TYPE string.
    DATA: v_name TYPE string READ-ONLY.
ENDCLASS.                    "lcl_item DEFINITION
*
CLASS lcl_item IMPLEMENTATION.
  METHOD constructor.
    v_name = iv_name.
  ENDMETHOD.                    "constructor
ENDCLASS.                    "lcl_item IMPLEMENTATION
*
INTERFACE if_collection DEFERRED.
*
INTERFACE if_iterator.
  METHODS: get_index RETURNING value(index) TYPE i,
           has_next  RETURNING value(has_next) TYPE flag,
           get_next  RETURNING value(object) TYPE REF TO object,
           first     RETURNING value(object) TYPE REF TO object,
           set_step  IMPORTING value(iv_step) TYPE i.
  DATA: v_step TYPE i.
  DATA: v_current TYPE i.
  DATA: o_collection TYPE REF TO if_collection.
ENDINTERFACE.                    "if_iterator IMPLEMENTATION
*
INTERFACE if_collection.
  METHODS: get_iterator RETURNING value(iterator) TYPE REF TO if_iterator.
  METHODS: add    IMPORTING element TYPE REF TO object,
           remove IMPORTING element TYPE REF TO object,
           clear,
           size   RETURNING value(size) TYPE i,
           is_empty RETURNING value(empty) TYPE flag,
           get    IMPORTING index TYPE i
                  RETURNING value(object) TYPE REF TO object.
ENDINTERFACE.                    "if_collection IMPLEMENTATION
*
CLASS lcl_iterator DEFINITION.
  PUBLIC SECTION.
    INTERFACES: if_iterator.
    METHODS: constructor IMPORTING io_collection TYPE REF TO if_collection.
    ALIASES: get_index   FOR if_iterator~get_index,
             has_next    FOR if_iterator~has_next,
             get_next    FOR if_iterator~get_next,
             first       FOR if_iterator~first,
             set_step    FOR if_iterator~set_step.
 
  PRIVATE SECTION.
    ALIASES: v_step      FOR if_iterator~v_step,
             v_current   FOR if_iterator~v_current,
             o_collection FOR if_iterator~o_collection.
ENDCLASS.                    "lcl_iterator DEFINITION
*
CLASS lcl_collection DEFINITION.
  PUBLIC SECTION.
    INTERFACES: if_collection.
    DATA: i_items TYPE STANDARD TABLE OF REF TO object.
    ALIASES: get_iterator   FOR if_collection~get_iterator,
             add            FOR if_collection~add,
             remove         FOR if_collection~remove,
             clear          FOR if_collection~clear,
             size           FOR if_collection~size,
             is_empty       FOR if_collection~is_empty,
             get            FOR if_collection~get.
ENDCLASS.                    "lcl_collection DEFINITION
 
*
CLASS lcl_collection IMPLEMENTATION.
  METHOD if_collection~get_iterator.
    CREATE OBJECT iterator
      TYPE
        lcl_iterator
      EXPORTING
        io_collection = me.
  ENDMETHOD.                    "if_collection~get_iterator
  METHOD if_collection~add.
    APPEND element TO i_items.
  ENDMETHOD.                    "if_collection~add
  METHOD if_collection~remove.
    DELETE i_items WHERE table_line EQ element.
  ENDMETHOD.                    "if_collection~remove
  METHOD if_collection~clear.
    CLEAR: i_items.
  ENDMETHOD.                    "if_collection~clear
  METHOD if_collection~size.
    size = LINES( i_items ).
  ENDMETHOD.                    "if_collection~size
  METHOD if_collection~is_empty.
    IF me->size( ) IS INITIAL.
      empty = 'X'.
    ENDIF.
  ENDMETHOD.                    "if_collection~is_empty
  METHOD if_collection~get.
    READ TABLE i_items INTO object INDEX index.
  ENDMETHOD.                    "if_collection~get
ENDCLASS.                    "lcl_collection IMPLEMENTATION
*
CLASS lcl_iterator IMPLEMENTATION.
  METHOD constructor.
    o_collection = io_collection.
    v_step = 1.
  ENDMETHOD.                    "constructor
  METHOD if_iterator~first.
    v_current = 1.
    object = o_collection->get( v_current ).
  ENDMETHOD.                    "if_iterator~first
  METHOD if_iterator~get_next.
    v_current = v_current + v_step.
    object = o_collection->get( v_current ).
  ENDMETHOD.                    "if_iterator~next
  METHOD if_iterator~has_next.
    DATA obj TYPE REF TO object.
    DATA idx TYPE i.
    idx = v_current + v_step.
    obj = o_collection->get( idx ).
    IF obj IS BOUND.
      has_next = 'X'.
    ENDIF.
  ENDMETHOD.                    "if_iterator~isdone
  METHOD if_iterator~set_step.
    me->v_step = iv_step.
  ENDMETHOD.                    "if_iterator~SET_STEP
  METHOD if_iterator~get_index.
    index = index.
  ENDMETHOD.                    "if_iterator~get_index
ENDCLASS.                    "iterator IMPLEMENTATION
*
CLASS lcl_main DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: run.
ENDCLASS.                    "lcl_main DEFINITION
*
CLASS lcl_main IMPLEMENTATION.
  METHOD run.
*
    DATA: o_collection TYPE REF TO if_collection.
    DATA: o_iterator TYPE REF TO if_iterator.
    DATA: lo_item TYPE REF TO lcl_item.
 
    CREATE OBJECT o_collection TYPE lcl_collection.
    o_iterator = o_collection->get_iterator( ).
 
    CREATE OBJECT lo_item
      EXPORTING
        iv_name = 'Item1'.
    o_collection->add( lo_item ).
    CREATE OBJECT lo_item
      EXPORTING
        iv_name = 'Item2'.
    o_collection->add( lo_item ).
    CREATE OBJECT lo_item
      EXPORTING
        iv_name = 'Item3'.
    o_collection->add( lo_item ).
    CREATE OBJECT lo_item
      EXPORTING
        iv_name = 'Item4'.
    o_collection->add( lo_item ).
    CREATE OBJECT lo_item
      EXPORTING
        iv_name = 'Item5'.
    o_collection->add( lo_item ).
 
    "o_iterator->set_step( 2 ).
    WHILE o_iterator->has_next( ) IS NOT INITIAL.
      lo_item ?= o_iterator->get_next( ).
      WRITE: / lo_item->v_name.
    ENDWHILE.
  ENDMETHOD.                    "run
ENDCLASS.                    "lcl_main IMPLEMENTATION
 
START-OF-SELECTION.
  lcl_main=>run( ).
 

Should we implement Iterator in ABAP?

At first its seems too much overhead implementing the Iterator Design Pattern in ABAP as we have Iternal Tables. We can create internal tables which can contain the Objects and perform the operations like reading an entry, adding new entries, deleting entries etc. To implement the iterator design pattern, we need to create a separate Iterator object which would traverse through the collected objects in the collection. This collection would be generally the ITAB containg all the objects.

We should try to implement Iterator because,

  • We could create as many iterator as we want to traverse objects in the different sequence.
  • Linked List Object collection – When we need to use the Linked List type of the object collection, it would be difficult for every client to implement the accessing algorithm. Rather than that, we can create the Iterator and all clients can straight away use Iterator to access any object collection – ITAB or Linked List.

Do you agree on this?

Check out all Design Patterns

You may also want to explore all other Design Patterns in OO ABAP.

I’ll write in next post on how to implement Linked List in OOABAP and use Iterator to process it.

Like It? Share!!

Don't miss an Update

Get notified of the new post, right into your inbox

Naimesh Patel{272 articles}

I'm SAP ABAP Consultant for more than a decade. I like to experiment with ABAP especially OO. I have been SDN Top Contributor.
Follow :

Explore all of his 272 articles.

Load comments

5 Comments

  • [...] the previous post, you have seen how to implement Iterator design Pattern. It also raised the question about the usefulness in ABAP as in ABAP, you have Internal Tables. The [...]

  • marcin

    Nice post. The only thing which could be changed/enhanced here is implementing LCL_ITERATOR within LCL_COLLECTION, not outside it (of course assuming both classes are global). This way we would achieve strong coupling b/w both classes, but eventually LCL_ITERATOR is dedicated for IF_COLLECTION. So all the objects implementing this interface would be acceptable by LCL_ITERATOR->CONSTRUCTOR.

    I described this global case here:
    http://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/25938

    ArrayList in Java is designed that way, by means of an inner class.
    Obviously we can’t achieve the similar in ABAP’s local class versions, so the only acceptable form is the one you lectured.

    Thanks
    Marcin

  • Wow, nice post on SDN. I don’t know how I missed that post.

    It intense of creating LCL_ITERATOR as separate is to LOOSELY couple it. As on the same Collector, you could have more than one Iterator – one traversing from top to bottom, one for bottom to top, one for objects at even positions, etc.

    If you have followed the next article for Iterator Iterator Design Pattern to access Linked List in ABAP Objects, the iterator is exactly same for both LCL_COLLECTION and LCL_LINKED_COLLECTION – as both needs same top to bottom traversal.

    Regards,
    Naimesh Patel

  • marcin

    True. This way we can support serveral Iterators. I didn’t have chance to study next Iterator post yet, but surely will do this, as Linked List sounds as great fun :)

    Thanks
    marcin

  • kiran

    It was a real good website..i had got valuable information.

Comments on this Post are now closed. If you have something important to share, you can always contact me.

You seem to be new here. Subscribe to stay connected.