omposite allows clients to access individual object and composition objects in uniform way.
What is Composite?
Clients needs to work with hierarchical collection of objects – both “Primitive” and “Composite” objects. Primitive (individual) objects processing would be handled differently than the Composition of the objects. So, we will compose a tree structure which would contain both type of objects – Primitive as well as Collection of Primitive objects.
Sometimes we have to deal with Hierarchical or Tree type of data. The data which are related with each other and form a type of hierarchy. We can write the recursive logic to process related entries. But, the problem with the approach is : client has to distinguish between the type of objects, weather it is a end node or collection of nodes. It would become more complex as, we need to do this distinction all the time when we work with those objects. So, composite design pattern shows how to use recursive composition so that client doesn’t have to distinguish between the objects.
UML
Let check out the UML classes which we’ll use for the demo:
We have these components within the UML:
- LCL_SHAPE – This is an abstract class. Client would use this class to perform the operations. This is also referred as “Component”. Since it’s an abstract class, we can also implement default behavior.
- LCL_LINE – This is a concrete class inheriting from LCL_SAHPE. This would define the individual behavior of an object. This is known as “Leaf”. Leaf won’t have any kids, meaning no composition.
- LCL_PICTURE – Class which has a collection of objects. Combination of Lines would create the Picture. This is a “Composite” object. This class would have an internal table defined with referenced to Component. This internal table would contain all the “Kids” which would involve processing of the object. This objects executes operation of each and every individual object. Client would not have to distinguish between the Leaf and Composition. We can simply call the Composition behavior and all it would take care of processing each and every kids operations.
Code Lines
Here is the demo program to show the Composite design pattern implementation in ABAP.
Composite Design Pattern Demo
REPORT ZNP_DP_COMPOSITE. CLASS lcl_shape DEFINITION ABSTRACT. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE STRING, ADD ABSTRACT IMPORTING io_shape TYPE REF TO lcl_shape, remove ABSTRACT IMPORTING io_shape TYPE REF TO lcl_shape, display ABSTRACT IMPORTING indent TYPE i. PROTECTED SECTION. DATA: v_name TYPE STRING. ENDCLASS. * CLASS lcl_shape IMPLEMENTATION. METHOD constructor. me->v_name = iv_name. ENDMETHOD. ENDCLASS. * CLASS lcl_line DEFINITION INHERITING FROM lcl_shape. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE STRING. METHODS: ADD REDEFINITION, remove REDEFINITION, display REDEFINITION. ENDCLASS. * CLASS lcl_line IMPLEMENTATION. METHOD constructor. super->constructor( iv_name ). ENDMETHOD. METHOD ADD. WRITE : / 'Can not add'. ENDMETHOD. METHOD remove. WRITE : / 'Can not delete'. ENDMETHOD. METHOD display. WRITE : / ". DO indent TIMES. WRITE: '-'. ENDDO. WRITE : v_name. ENDMETHOD. ENDCLASS. * CLASS lcl_picture DEFINITION INHERITING FROM lcl_shape. PUBLIC SECTION. METHODS:constructor IMPORTING iv_name TYPE STRING. METHODS: ADD REDEFINITION, remove REDEFINITION, display REDEFINITION. PRIVATE SECTION. TYPES: BEGIN OF lty_shapes, o_shape TYPE REF TO lcl_shape, end OF lty_shapes. * data: li_shapes type STANDARD TABLE OF lty_shapes. DATA: li_shapes TYPE STANDARD TABLE OF REF TO lcl_shape. ENDCLASS. * CLASS lcl_picture IMPLEMENTATION. METHOD constructor. super->constructor( iv_name ). ENDMETHOD. METHOD ADD. APPEND io_shape TO li_shapes. ENDMETHOD. METHOD remove. DELETE li_shapes WHERE TABLE_LINE EQ io_shape. ENDMETHOD. METHOD display. DATA: lo_shape TYPE REF TO lcl_shape. WRITE: / ". DO indent TIMES. WRITE: (2) '-'. ENDDO. WRITE: v_name. DATA: lv_indent TYPE i. lv_indent = indent + 1. * Processing each primitive object within the composition LOOP AT li_shapes INTO lo_shape. lo_shape->display( lv_indent ). ENDLOOP. ENDMETHOD. ENDCLASS. * CLASS lcl_main DEFINITION. PUBLIC SECTION. CLASS-METHODS: run. ENDCLASS. * CLASS lcl_main IMPLEMENTATION. METHOD run. DATA: lo_pic TYPE REF TO lcl_shape. DATA: lo_shape TYPE REF TO lcl_shape. CREATE OBJECT lo_pic TYPE lcl_picture EXPORTING iv_name = 'Picture'. CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Left Line'. lo_pic->add( lo_shape ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Top Line'. lo_pic->add( lo_shape ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Right Line'. lo_pic->add( lo_shape ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Bottom Line'. lo_pic->add( lo_shape ). DATA: lo_pic2 TYPE REF TO lcl_shape. CREATE OBJECT lo_pic2 TYPE lcl_picture EXPORTING iv_name = 'Picture 2'. CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Left Line'. lo_pic2->add( lo_shape ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Top Line'. lo_pic2->add( lo_shape ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Right Line'. lo_pic2->add( lo_shape ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'Bottom Line'. lo_pic2->add( lo_shape ). lo_pic->add( lo_pic2 ). CREATE OBJECT lo_shape TYPE lcl_line EXPORTING iv_name = 'text'. lo_pic->add( lo_shape ). * Uniform way to access the composition - it could be a primitive object * or composition itself. lo_pic->display( 1 ). ENDMETHOD. ENDCLASS. * START-OF-SELECTION. lcl_main=>run( ).
Design Time Consideration:
We should follow these steps to achieve Composite Design Pattern.
- Create an Abstract Class
- Inherit an individual class with certain behavior
- Inherit a composite class which would store the Kids objects. Operation of Composite objects should actually perform the operations of each child.
- Client should use Component Abstract class to interact with composite objects.
No comments:
Post a Comment