{"id":1169,"date":"2014-10-16T08:01:08","date_gmt":"2014-10-16T07:01:08","guid":{"rendered":"http:\/\/oprsteny.cz\/?p=1169"},"modified":"2014-10-16T08:01:08","modified_gmt":"2014-10-16T07:01:08","slug":"design-patterns-in-abap-observer","status":"publish","type":"post","link":"https:\/\/oprsteny.cz\/?p=1169","title":{"rendered":"Design Patterns in ABAP &#8211; Observer"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"358\" data-permalink=\"https:\/\/oprsteny.cz\/?attachment_id=358\" data-orig-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/SAP.jpg\" data-orig-size=\"44,50\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;Picasa&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;1365690880&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"SAP\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/SAP.jpg\" class=\"size-full wp-image-358 alignleft\" src=\"http:\/\/oprsteny.cz\/wp-content\/uploads\/SAP.jpg\" alt=\"SAP\" width=\"44\" height=\"50\" \/>Observer design pattern can be easily demonstrated on a <em>chat service where<\/em> you have a <em>server<\/em> and several <em>clients<\/em> (<em>observers<\/em>). Once a client sends a message, server receives it and RAISES an <em><strong>EVENT<\/strong><\/em> (eg NEW_MESSAGE_RECEIVED) which is OBSERVED by all connected clients (<em>observers) <\/em>and such message is subsequently displayed in message dialog on all clients.<!--more--><\/p>\n<p>In ABAP world it can be demonstrated eg. on an ALV where a change in it&#8217;s cell contents raises an event which is observed and further handled in various observers (eg another ALV which automatically updates its contents).<\/p>\n<p>In our example we will have a server (main process) which will trigger an EVENT each time a message is received.<br \/>\nAll registered clients (in our case it will be a <em>Dialog<\/em> and <em>Printer<\/em> clients) will handle the event according to their implementations.<\/p>\n<p><a href=\"http:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02.png\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1170\" data-permalink=\"https:\/\/oprsteny.cz\/?attachment_id=1170\" data-orig-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02.png\" data-orig-size=\"697,373\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Observer Class diagram\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02.png\" class=\"size-medium wp-image-1170 aligncenter\" src=\"http:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02-300x160.png\" alt=\"Observer Class diagram\" width=\"300\" height=\"160\" srcset=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02-300x160.png 300w, https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02-500x267.png 500w, https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_02.png 697w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Server part<\/h2>\n<p>Our server (main process) receives a message from clients via public method PUT_MESSAGE and can raise an event called NEW_MESSAGE.<\/p>\n<pre lang=\"abap\">*** SERVER PART ***\r\nCLASS lcl_server DEFINITION.\r\n  PUBLIC SECTION.\r\n    METHODS:\r\n      put_message IMPORTING i_msg TYPE string.\r\n    EVENTS\r\n      new_message EXPORTING VALUE(msg) TYPE string.\r\nENDCLASS.\r\n\r\nCLASS lcl_server IMPLEMENTATION.\r\n  METHOD put_message.\r\n*** Debug info ***\r\n    WRITE:\/ 'Server received new message:'.\r\n    WRITE:\/ '  ', i_msg.\r\n\r\n    WRITE:\/ 'Server raises event NEW_MESSAGE'.\r\n    SKIP 2.\r\n    RAISE EVENT new_message EXPORTING msg = i_msg.\r\n  ENDMETHOD.\r\nENDCLASS.<\/pre>\n<h2>Client interface<\/h2>\n<p>Because we can have multiple clients handling the data differently, we implemented a common interface that all clients will use, but the behaviour of each client can be different in it&#8217;s implementation as I&#8217;ll show later with a DIALOG and a PRINTER clients.<\/p>\n<pre lang=\"abap\">*** CLIENT INTERFACE ***\r\nINTERFACE lif_client.\r\n  METHODS:\r\n    send IMPORTING i_msg TYPE string,\r\n    on_new_message FOR EVENT new_message OF lcl_server\r\n      IMPORTING msg.\r\n  DATA:\r\n    mo_server TYPE REF TO lcl_server READ-ONLY.\r\nENDINTERFACE.<\/pre>\n<h2>Dialog Client<\/h2>\n<pre lang=\"abap\">*** DIALOG CLIENT ***\r\nCLASS lcl_dialog_client DEFINITION.\r\n  PUBLIC SECTION.\r\n    INTERFACES lif_client.\r\n    METHODS:\r\n      constructor\r\n        IMPORTING\r\n          io_server TYPE REF TO lcl_server.\r\nENDCLASS.\r\n\r\nCLASS lcl_dialog_client IMPLEMENTATION.\r\n  METHOD constructor.\r\n    lif_client~mo_server = io_server.\r\n  ENDMETHOD.\r\n\r\n  METHOD lif_client~send.\r\n*** Debug info ***\r\n    WRITE: \/ 'DIALOG is sending new message'.\r\n    lif_client~mo_server-&gt;put_message(\r\n      EXPORTING\r\n        i_msg = i_msg\r\n    ).\r\n  ENDMETHOD.\r\n\r\n  METHOD lif_client~on_new_message.\r\n*** Debug info ***\r\n    WRITE: \/ 'DIALOG received new message:'.\r\n    WRITE: \/ '  ', msg.\r\n  ENDMETHOD.\r\nENDCLASS.<\/pre>\n<h2>Printer Client<\/h2>\n<pre lang=\"abap\">*** PRINTER CLIENT ***\r\nCLASS lcl_printer_client DEFINITION.\r\n  PUBLIC SECTION.\r\n    INTERFACES lif_client.\r\n    METHODS:\r\n      constructor\r\n        IMPORTING\r\n          io_server TYPE REF TO lcl_server.\r\nENDCLASS.\r\n\r\nCLASS lcl_printer_client IMPLEMENTATION.\r\n  METHOD constructor.\r\n    lif_client~mo_server = io_server.\r\n  ENDMETHOD.\r\n\r\n  METHOD lif_client~send.\r\n*** Debug info ***\r\n    WRITE: \/ 'PRINTER is sending new message'.\r\n    lif_client~mo_server-&gt;put_message(\r\n      EXPORTING\r\n        i_msg = i_msg\r\n    ).\r\n  ENDMETHOD.\r\n\r\n  METHOD lif_client~on_new_message.\r\n*** Debug info ***\r\n    WRITE: \/ 'PRINTER received new message:'.\r\n    WRITE: \/ '  ', msg.\r\n  ENDMETHOD.\r\nENDCLASS.<\/pre>\n<h2>Test program<\/h2>\n<pre lang=\"abap\">*** TEST PROGRAM ***\r\nSTART-OF-SELECTION.\r\n  DATA:\r\n    lo_server   TYPE REF TO lcl_server,\r\n    lo_client_1 TYPE REF TO lif_client,\r\n    lo_client_2 TYPE REF TO lif_client.\r\n\r\n* Creating server instance\r\n  CREATE OBJECT lo_server.\r\n* Creating dialog client instance\r\n  CREATE OBJECT lo_client_1 TYPE lcl_dialog_client\r\n    EXPORTING\r\n      io_server = lo_server.\r\n* Creating printer client instance\r\n  CREATE OBJECT lo_client_2 TYPE lcl_printer_client\r\n    EXPORTING\r\n      io_server = lo_server.\r\n\r\n* Register event handlers\r\n  SET HANDLER lo_client_1-&gt;on_new_message FOR lo_server.\r\n  SET HANDLER lo_client_2-&gt;on_new_message FOR lo_server.\r\n\r\n* Send new message from dialog client to server\r\n  lo_client_1-&gt;send( 'Hello world' ).<\/pre>\n<h2>Output<\/h2>\n<p><a href=\"http:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_01.png\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1168\" data-permalink=\"https:\/\/oprsteny.cz\/?attachment_id=1168\" data-orig-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_01.png\" data-orig-size=\"237,285\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Observer design pattern &amp;#8211; Output\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_01.png\" class=\"size-full wp-image-1168 aligncenter\" src=\"http:\/\/oprsteny.cz\/wp-content\/uploads\/DESIGN_PATTERNS_OBSERVER_01.png\" alt=\"Observer design pattern - Output\" width=\"237\" height=\"285\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Observer design pattern can be easily demonstrated on a chat service where you have a server and several clients (observers). Once a client sends a message, server receives it and RAISES an EVENT (eg NEW_MESSAGE_RECEIVED) which is OBSERVED by all &hellip; <a href=\"https:\/\/oprsteny.cz\/?p=1169\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Design Patterns in ABAP - Observer","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[16,15,8,4,9],"tags":[343,335,341,342,221,344],"class_list":["post-1169","post","type-post","status-publish","format-standard","hentry","category-abap","category-algorithms","category-behavioral-patterns","category-design-patterns","category-development","tag-client","tag-design-patterns-2","tag-interface","tag-observer","tag-oo-abap","tag-server"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p3nYbe-iR","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts\/1169","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1169"}],"version-history":[{"count":1,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts\/1169\/revisions"}],"predecessor-version":[{"id":1171,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=\/wp\/v2\/posts\/1169\/revisions\/1171"}],"wp:attachment":[{"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1169"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1169"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oprsteny.cz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1169"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}