2009 Dec 22 12:23 AM
When trying to implement the classic decorator design patterns your decorator executable might look like this:<br><br>
<pre>
METHOD validate.
DATA: Validator TYPE REF TO validation_manager.
CREATE OBJECT:
Validator TYPE validation_manager.
,Validator TYPE validate_format EXPORTING x_validator = Validator
,Validator TYPE validate_values EXPORTING x_validator = Validator
,Validator TYPE validate_relation_input EXPORTING x_validator = Validator
,Validator TYPE validate_relation_database EXPORTING x_validator = Validator.
me->lst_result = validator->validate( me->lst_data ).
WRITE: / 'Processing Validate Activity'.
ENDMETHOD. "validate</pre><br><br>
The validate method ends up in endless resurcion in the memory. The reason is that I'm using the same variable as the resulting instanse and as parameter. It seems like the constructor treats both the result and the parameter as the same field/instanse regardless import parameter such as VALUE/REFERENCE. If I change the method to use an extra field in the method validate like:
<br><br><pre>
METHOD validate.
DATA:
validator TYPE REF TO validation_manager
,recursive TYPE REF TO validation_manager.
CREATE OBJECT validator TYPE validation_manager.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_format
EXPORTING x_validator = recursive.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_values
EXPORTING x_validator = recursive.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_relation_input
EXPORTING x_validator = recursive.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_relation_database
EXPORTING x_validator = recursive .
recursive ?= validator.
me->lst_result = validator->validate( me->lst_data ).
WRITE: / 'Processing Validate Activity'.
ENDMETHOD. "validate</pre><br><br>
Now the decorator engine works, but why does the first implementation not work when the same one executes fine in php, c++, delphi, java and other languages.<br><br>
If you do not know what I'm trying to discuss, look up "Design Patterns - Simply", and jump to the chapter about the decorator design pattern. I'm trying to use this design pattern for a validation manager within my Business Process Engine, which needs to be able to configure what types of validation needed for on specific process (BPMN).<br><br>
2009 Dec 22 2:36 PM
It goes into endless LOOP because when system executes this statement it carries the new object created in the X_VALIDATOR parameter. So, the object has the reference of its OWN object instead of the SUPER object. This happens because as soon as system executes the statement CREATE OBJECT it creates the object before calling the constructor. SO, when it reaches to constructor it has its OWN object reference instead of the SUPER object reference.
CREATE OBJECT:
validator TYPE validation_manager
,Validator TYPE validate_format EXPORTING x_validator = Validator
From Help:
The CREATE OBJECT statement creates an instance of a class or object and assigns the object reference to the reference variable oref. Directly after the object has been created, the instance constructor of the class is executed.
http://help.sap.com/abapdocu_70/en/ABAPCREATE_OBJECT.htm
So, you need to use the temporary variable to hold the super's reference and pass this variable while instantiating the object.
Regards,
Naimesh Patel
It goes into endless LOOP because when system executes this statement it carries the new object created in the X_VALIDATOR parameter. So, the object has the reference of its OWN object instead of the SUPER object. This happens because as soon as system executes the statement CREATE OBJECT it creates the object before calling the constructor. SO, when it reaches to constructor it has its OWN object reference instead of the SUPER object reference.
CREATE OBJECT:
validator TYPE validation_manager
,Validator TYPE validate_format EXPORTING x_validator = Validator
From Help:
The CREATE OBJECT statement creates an instance of a class or object and assigns the object reference to the reference variable oref. Directly after the object has been created, the instance constructor of the class is executed.
http://help.sap.com/abapdocu_70/en/ABAPCREATE_OBJECT.htm
So, you need to use the temporary variable to hold the super's reference and pass this variable while instantiating the object.
Regards,
Naimesh Patel
2009 Dec 22 6:47 AM
2009 Dec 22 6:51 AM
2009 Dec 22 11:31 AM
Hi Matt, Thanks for the formatting..:) I will post the complete program as it's only a prototype program. Trying to get the format under control.
</body>
}*----
*
Report ZDP_DECORATOR_XMP01
*----
*
REPORT zdp_decorator_xmp01.
parameters: bestimpl TYPE boolean_01 default 0.
TYPES:
BEGIN OF processdata
,name TYPE char30
,street TYPE char30
,zip TYPE char5
,city TYPE char30
,email TYPE char50
,phone TYPE char20
,END OF processdata
,BEGIN OF result
,msgid TYPE msgid
,msgtyp TYPE msgty
,msgno TYPE msgno
,status TYPE char1
,END OF result.
CONSTANTS:
true TYPE boolean_01 VALUE 1
,false TYPE boolean_01 VALUE 0.
*----
*
CLASS validationmanager DEFINITION
*----
*
CLASS validation_manager DEFINITION.
PUBLIC SECTION.
METHODS:
validate
IMPORTING
x_data TYPE processdata
RETURNING
value(y_result) TYPE result.
ENDCLASS.
*----
*
CLASS validationmanager IMPLEMENTATION
*----
*
CLASS validation_manager IMPLEMENTATION.
METHOD validate.
WRITE: / 'Common validation'.
ENDMETHOD. "validate
ENDCLASS.
*----
*
CLASS Validate_Decorator DEFINITION
*----
*
CLASS validate_decorator DEFINITION INHERITING FROM validation_manager ABSTRACT .
PUBLIC SECTION.
DATA: validator TYPE REF TO validation_manager.
ENDCLASS.
*----
*
CLASS validate_format DEFINITION
*----
*
CLASS validate_format DEFINITION INHERITING FROM validate_decorator.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING value(x_validator) TYPE REF TO validation_manager
,validate REDEFINITION.
ENDCLASS.
*----
*
CLASS validate_format IMPLEMENTATION
*----
*
CLASS validate_format IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor( ).
me->validator = x_validator.
ENDMETHOD. "constructor
METHOD validate.
y_result = validator->validate( x_data ).
IF y_result-status IS INITIAL.
WRITE: / 'Now doing the format checks'.
ENDIF.
ENDMETHOD. "validate
ENDCLASS.
*----
*
CLASS validate_values DEFINITION
*----
*
CLASS validate_values DEFINITION INHERITING FROM validate_decorator.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING value(x_validator) TYPE REF TO validation_manager
,validate REDEFINITION.
ENDCLASS.
*----
*
CLASS validate_values IMPLEMENTATION
*----
*
CLASS validate_values IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor( ).
me->validator = x_validator.
ENDMETHOD. "constructor
METHOD validate.
y_result = validator->validate( x_data ).
IF y_result-status IS INITIAL.
WRITE: / 'Now doing the values checks'.
ENDIF.
ENDMETHOD. "validate
ENDCLASS.
*----
*
CLASS validate_relation_input DEFINITION
*----
*
CLASS validate_relation_input DEFINITION INHERITING FROM validate_decorator.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING value(x_validator) TYPE REF TO validation_manager
,validate REDEFINITION.
ENDCLASS.
*----
*
CLASS validate_relation_input IMPLEMENTATION
*----
*
CLASS validate_relation_input IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor( ).
me->validator = x_validator.
ENDMETHOD. "constructor
METHOD validate.
y_result = validator->validate( x_data ).
IF y_result-status IS INITIAL.
WRITE: / 'Now doing the relation input checks'.
ENDIF.
ENDMETHOD. "validate
ENDCLASS.
*----
*
CLASS validate_relation_database DEFINITION
*----
*
CLASS validate_relation_database DEFINITION INHERITING FROM validate_decorator.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING value(x_validator) TYPE REF TO validation_manager
,validate REDEFINITION.
ENDCLASS.
*----
*
CLASS validate_relation_database IMPLEMENTATION
*----
*
CLASS validate_relation_database IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor( ).
me->validator = x_validator.
ENDMETHOD. "constructor
METHOD validate.
y_result = validator->validate( x_data ).
IF y_result-status IS INITIAL.
WRITE: / 'Now doing the relation database checks'.
ENDIF.
ENDMETHOD. "validate
ENDCLASS.
*----
*
CLASS process_execution DEFINITION
*----
*
CLASS process_execution DEFINITION.
PUBLIC SECTION.
METHODS:
startevent
,getdata
,validate
,process
,endevent.
PRIVATE SECTION.
DATA:
lst_data TYPE processdata
,lst_result TYPE result.
ENDCLASS. "process_execution DEFINITION
*----
*
CLASS process_execution IMPLEMENTATION
*----
*
CLASS process_execution IMPLEMENTATION.
METHOD startevent.
WRITE: / 'Processing startevent'.
ENDMETHOD. "startevent
METHOD getdata.
me->lst_data-name = 'Hans Andersen'.
me->lst_data-street = 'H.C Andersens Boulevard 112'.
me->lst_data-zip = '1557'.
me->lst_data-city = 'København'.
me->lst_data-email = 'hcATandersen.dk'.
me->lst_data-phone = '0045-31162211'.
WRITE: / 'Processing Get_Data Activity'.
ENDMETHOD. "getdata
*----
*
*----
*
METHOD validate.
DATA:
validator TYPE REF TO validation_manager
,recursive TYPE REF TO validation_manager
.
IF bestimpl = true.
CREATE OBJECT:
validator TYPE validation_manager
,validator TYPE validate_format EXPORTING x_validator = recursive
,validator TYPE validate_values EXPORTING x_validator = recursive
,validator TYPE validate_relation_input EXPORTING x_validator = recursive
,validator TYPE validate_relation_database EXPORTING x_validator = recursive.
ELSE.
CREATE OBJECT validator TYPE validation_manager.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_format
EXPORTING x_validator = recursive.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_values
EXPORTING x_validator = recursive.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_relation_input
EXPORTING x_validator = recursive.
recursive ?= validator.
CREATE OBJECT validator TYPE validate_relation_database
EXPORTING x_validator = recursive .
recursive ?= validator.
ENDIF.
Recursive call of the validate and it's successors
me->lst_result = validator->validate( me->lst_data ).
WRITE: / 'Processing Validate Activity'.
ENDMETHOD. "validate
METHOD process.
WRITE: / 'Processing Process Activity'.
ENDMETHOD. "process
METHOD endevent.
WRITE: / 'Processing endevent'.
ENDMETHOD. "endevent
ENDCLASS.
*----
*
CLASS mainapp DEFINITION *
*----
*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
*----
*
CLASS mainapp IMPLEMENTATION *
*----
*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA:
p89 TYPE REF TO process_execution.
CREATE OBJECT p89.
p89->startevent( ).
p89->getdata( ).
p89->validate( ).
p89->process( ).
p89->endevent( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
mainapp=>main( ).
Edited by: Matt on Dec 22, 2009 2:03 PM Fixed formatting
2009 Dec 22 2:36 PM
It goes into endless LOOP because when system executes this statement it carries the new object created in the X_VALIDATOR parameter. So, the object has the reference of its OWN object instead of the SUPER object. This happens because as soon as system executes the statement CREATE OBJECT it creates the object before calling the constructor. SO, when it reaches to constructor it has its OWN object reference instead of the SUPER object reference.
CREATE OBJECT:
validator TYPE validation_manager
,Validator TYPE validate_format EXPORTING x_validator = Validator
From Help:
The CREATE OBJECT statement creates an instance of a class or object and assigns the object reference to the reference variable oref. Directly after the object has been created, the instance constructor of the class is executed.
http://help.sap.com/abapdocu_70/en/ABAPCREATE_OBJECT.htm
So, you need to use the temporary variable to hold the super's reference and pass this variable while instantiating the object.
Regards,
Naimesh Patel
2009 Dec 22 6:18 PM
As I mentioned in an email discussion with Benny - there are some seriously talented people in this forum.
2009 Dec 22 7:01 PM
| User | Count |
|---|---|
| 4 | |
| 2 | |
| 2 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 |