The intent behind the Observer Design Pattern is to define a dependecy between objects so that when main object changes its state, all the dependent objects are notified. Its upto the dependent objects to update themselves or ignore the notification.
Design time consideration
- In the main object, AKA Subject, create a Event. Also add create a signature to the event.
- Create class with Event Handler method for the event of the Subject.
- Inherit the Subclasses for different behavior. Redefine the event handler method for which any behavior is required.
- Register the event handler using the statement
SET EVENT HANDLER ... FOR O_SUBJECT
.
UML
Lets see the UML for the example.
We have a Subject class as MAINPROCESS
. This class has the event as STATE_CHANGED
. We would trigger the event whenever there is any change in the state of the object. Thus, we raise the event when we set the new status of the object – attribute CURRENT_STATE
using the method SET_STATE( )
.
We have an abstract super class MYFUNCTION
. We created event handler method ON_STATE_CHANGED
for the event STATE_CHANGED
of class MAINPROCESS
. We inherite two classes MYALV
and MYDB
from it. We redefine the methods to refresh their status.
Code Lines
Here is the Code lines.
program znp_dp_observer.
*====
CLASS mainprocess DEFINITION.
PUBLIC SECTION.
METHODS: set_state IMPORTING iv_state TYPE char1.
EVENTS: state_changed EXPORTING value(new_state) TYPE char1.
PRIVATE SECTION.
DATA: current_state TYPE char1.
ENDCLASS. "mainprocess DEFINITION
*
CLASS mainprocess IMPLEMENTATION.
METHOD set_state.
current_state = iv_state.
SKIP 2.
WRITE: / 'Main Process new state', current_state.
RAISE EVENT state_changed EXPORTING new_state = current_state.
ENDMETHOD. "set_state
ENDCLASS. "mainprocess IMPLEMENTATION
*====
CLASS myfunction DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS: on_state_changed ABSTRACT
FOR EVENT state_changed OF mainprocess
IMPORTING new_state.
ENDCLASS. "myfunction DEFINITION
*====
CLASS myalv DEFINITION INHERITING FROM myfunction.
PUBLIC SECTION.
METHODS: on_state_changed REDEFINITION.
ENDCLASS. "myalv DEFINITION
*
CLASS myalv IMPLEMENTATION.
METHOD on_state_changed.
WRITE: / 'New state in ALV processing', new_state.
ENDMETHOD. "on_state_changed
ENDCLASS. "myalv IMPLEMENTATION
*====
CLASS mydb DEFINITION INHERITING FROM myfunction.
PUBLIC SECTION.
METHODS: on_state_changed REDEFINITION.
ENDCLASS. "mydb DEFINITION
*
CLASS mydb IMPLEMENTATION.
METHOD on_state_changed.
WRITE: / 'New State in DB processing', new_state.
ENDMETHOD. "on_state_changed
ENDCLASS. "mydb IMPLEMENTATION
*====
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: run.
ENDCLASS. "mainapp DEFINITION
*
CLASS mainapp IMPLEMENTATION.
METHOD run.
DATA: lo_process TYPE REF TO mainprocess.
DATA: lo_alv TYPE REF TO myalv.
DATA: lo_db TYPE REF TO mydb.
* Instantiate the objects
CREATE OBJECT lo_process.
CREATE OBJECT: lo_alv, lo_db.
* Event handlers
SET HANDLER lo_alv->on_state_changed FOR lo_process.
SET HANDLER lo_db->on_state_changed FOR lo_process.
* Set new state
lo_process->set_state( 'A' ).
lo_process->set_state( 'B' ).
lo_process->set_state( 'C' ).
ENDMETHOD. "run
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>run( ).
Explanation
When we call method SET_STATUS
of the object LO_PROCESS
, it raises the event STATE_CHANGED
. This would be caught in the event handler ON_STATE_CHANGED
. This is possible with the statement, SET HANDLER lo_alv->on_state_changed FOR lo_process
.
Output
The test program generate this output:
Don’t miss to read, The Case Study: Observer Design Pattern Usage to know more about how observer can be implemented in real-world.
SDN Wiki – Observer Design Pattern
SDN Forum – Observer Design Pattern: Looking for redesign ABAP OO code example