Skip to Content

This blog is the second part of the blog series on Strategy Design Pattern:

So before we start using the Strategy Pattern let us revisit what we have learnt about Strategy Design Pattern!

1. Brushing up on Strategy Pattern

Let us recapitulate what we’ve learnt so far about Strategy pattern:

 

  • Strategy is, “A set (or family) of encapsulated algorithms (read: classes) which behave independently of the client using it.

 

Figure 1 – UML representation of Strategy Pattern

 

  • Strategy can be an interface or an abstract class. The idea here is to make the strategy to behave as polymorphic!
  • An attribute of the client stores the reference of the strategy object. Remember, the client never implements the strategy interface.
  • These algorithms are interchangeable at runtime via corresponding Setter methods.

2. Key points to remember while designing a Strategy Pattern:

  • Identify the “functionalities” (or behaviours) which are variable. Define an interface (or an abstract class) which will represent these functionalities & implement them in concrete classes.
  • Clients who will be using the strategy must not implement it. They should rather store the reference of the strategy in an attribute (preferably private).
  • The client attribute storing the strategy can be changed at runtime by corresponding setter methods.

3. Time to get your hands dirty!

Before you start your coding, you may want to get your design approach validated by your peers. What better way to do it, than share your UML diagram!

 

Figure 2 – UML diagram for Flight Data Upload Program

 

Salient features of the design are:

  • The “File Upload” & “Write Log” functionalities are separated from the client. They are each represented by a set of classes which implement the respective interfaces viz., ZIF_UPLOAD_UTIL & ZIF_LOG_UTIL.
  • Depending on the functionality we need to provide, we add a class implementing the interface. For e.g., to cater to the PC file upload functionality we’ve created the class ZCL_PC_FILE implementing the ZIF_UPLOAD_UTIL interface.
  • The client, class ZCL_FLIGHTDATA_UPLOAD, has two attributes PO_UPLD_UTIL & PO_LOG_UTIL which store the object references of the “File Upload” & “Write Log” interfaces.
  • The client has corresponding Setter methods to alter the behaviour of the PO_UPLD_UTIL & PO_LOG_UTIL attributes dynamically.
METHOD set_upload_util.

  DATA: lv_class_name TYPE seoclsname,
        lo_upld_util  TYPE REF TO zif_upload_util.

* Whenever a new file upload technique is to be added, we
* modify this method by adding an extra WHEN clause

* Set the upload util
  CASE i_file_upload_type.
    WHEN zif_upload_util=>c_pc_file.
      lv_class_name = `ZCL_PC_FILE`. "For PC file
    WHEN zif_upload_util=>c_as_file.
      lv_class_name = `ZCL_APPL_SERVER_FILE`. "For appl server file

  ENDCASE.

  IF me->po_upld_util IS BOUND.
    CLEAR me->po_upld_util. "Delete the reference
  ENDIF.
* Create the new reference
  CREATE OBJECT me->po_upld_util TYPE (lv_class_name).
ENDMETHOD.
METHOD set_log_util.

  DATA: lo_log_util   TYPE REF TO zif_log_util,
        lv_class_name TYPE seoclsname.

* Whenever a new log writing technique is to be added, we
* enhance this method by adding an extra WHEN clause

* Set the upload util
  CASE i_log_write_type.
    WHEN zif_log_util=>c_classical.
      lv_class_name = `ZCL_CLASSICAL_LOG`. "For classical log
    WHEN zif_log_util=>c_appl_log.
      lv_class_name = `ZCL_APPLLOG`. "For appl log
  ENDCASE.

  IF me->po_log_util IS BOUND.
    CLEAR me->po_log_util. "Delete the old reference
  ENDIF.

  CREATE OBJECT me->po_log_util TYPE (lv_class_name)."Create the new reference

ENDMETHOD.

The class framework can be downloaded as a nugget here. For more information on how to upload the nugget visit SAPlink project page.

3.1. Using the Strategy DP Framework…

The program uses the client instance go_dataupld to process the data

  DATA: go_dataupld TYPE REF TO zcl_flightdata_upload.

**********************************************************************
*                      Data Processing Event
**********************************************************************
START-OF-SELECTION.
* Create the flight data upload object
  CREATE OBJECT go_dataupld.


*   §1.1 Whenever a new file upload technique is to be added, we
*        enhance this method by adding an extra WHEN clause
* Set the file upload attribute
  CASE 'X'.
    WHEN rb_pc."PC file upload
      go_dataupld->set_upload_util( zif_upload_util=>c_pc_file ).
    WHEN rb_app."Appl Server file upload
      go_dataupld->set_upload_util( zif_upload_util=>c_as_file ).
  ENDCASE.


*   §1.2 Whenever a new log writing technique is to be added, we
*        enhance this method by adding an extra WHEN clause
* Set the write log attribute
  CASE 'X'.
    WHEN rb_old."For Classical log
      go_dataupld->set_log_util( zif_log_util=>c_classical ).
    WHEN rb_applg."For Appl log
      go_dataupld->set_log_util( zif_log_util=>c_appl_log ).
  ENDCASE.

  go_dataupld->upload_file_data( ). "Upload the file data
  go_dataupld->upload_data_to_db( ). "Upload data to DB
  go_dataupld->write_log( ). "Write Log

N.B.: Actual file upload & log writing techniques are outside the scope of this blog.

3.2 Bring on the change…

As mentioned in the previous blog the users want to add FTP functionality to the current program, which is when you started exploring the design patterns. Let us see how Strategy DP helps keep your code flexible.

In order to add the FTP functionality to the program, you follow these steps:

 

  •  Add the FTP class to the File upload Strategy

Now that you have a file upload strategy, you just have to add a new class which will upload the file via FTP (for e.g., ZCL_FTP_FILE) which will implement the interface ZIF_UPLOAD_UTIL.

Figure 4 – FTP Element added to Selection-Screen 

 

  • Modify the set_upload_util( ) method of the flight data upload class for the newly added file upload technique
 
* Set the upload util
  CASE i_file_upload_type.
    WHEN zif_upload_util=>c_pc_file.
      lv_class_name = `ZCL_PC_FILE`. "For PC file
    WHEN zif_upload_util=>c_as_file.
      lv_class_name = `ZCL_APPL_SERVER_FILE`. "For appl server file
    WHEN zif_upload_util=>c_ftp_file.
      lv_class_name = `ZCL_FTP_FILE`. "For FTP file upload --> Add this line
  ENDCASE.
  • Modify the selection-screen to add the FTP element.

 

Figure 5 – FTP Element added to Selection-Screen

 

  •   Modify the program to accomodate the FTP functionality
 
  CASE 'X'.
    WHEN rb_pc."PC file upload
      go_dataupld->set_upload_util( zif_upload_util=>c_pc_file ).
    WHEN rb_app."Appl Server file upload
      go_dataupld->set_upload_util( zif_upload_util=>c_as_file ).
    WHEN rb_ftp.
      go_dataupld->set_upload_util( zif_upload_util=>c_ftp_file ). "--> We just need to add this line
  ENDCASE.

You can see that by implementing Strategy DP you’ve managed to loosely couple the “File Upload” functionality from the actual program. Your program needs a very minor fix to add this additional functionality.

If the users now want to write the log to an Application Server file, you know what to do.

4. Final word of caution

Now that you know “why” & “how” to implement Strategy design pattern, you will find more places to apply it.

IMHO, although DPs can be helpful remember not to overuse them. You don’t want to complicate your “Hello World” application, do you? Do not complicate your programs unnecessarily, always K.I.S.S!

To report this post you need to login first.

8 Comments

You must be Logged on to comment or reply to a post.

  1. Bruno Esperança

    Awesome Suhas,

    Unfortunately this gave me the urge to use this everywhere, completely disregarding the KISS principle… I hate Glam Rock anyways 😀

    Wouldn’t mind to see some new content from you!

    Best,

    Bruno

    (0) 

Leave a Reply