© James E. McDonough 2017

James E. McDonough, Object-Oriented Design with ABAP, 10.1007/978-1-4842-2838-8_12

12. Strategy Design Pattern

James E. McDonough

(1)Pennington, New Jersey, USA

The next stop on our voyage through the Design Patterns galaxy takes us to the Strategy design pattern, another of the design patterns found in the GoF catalog. We will find this design pattern useful when we need to be able to regard each class in a family of related classes as interchangeable . The Strategy design pattern exemplifies the power of independent interfaces .

The Right Tool for the Job

A Swiss Army Knife is a versatile, foldable, pocket-sized, multi-tool utility containing a variety of pivoting attachments suitable for use in everyday circumstances. Its handle is shaped to offer both comfort and dexterity to the person using it. Although there are many different models, a small version with only a few attachments might include the following:

  • Large knife blade

  • Small knife blade

  • Can opener

  • Straight-head screwdriver

More robust models offer additional attachments, including

  • Bottle cap remover

  • Phillips-head screwdriver

  • Nail file

  • Saw blade

  • Pliers

  • Scissors

  • Corkscrew

  • Compass

  • Magnifying lens

To use one of the many tools , simply unfold the corresponding attachment from its closed position into its locked open position and maneuver the tool by its handle. What makes this tool so comfortable to use is that each tool has the same handle, enabling the user to apply the same grip regardless of the actual function the tool is providing.

Imagine we are having dinner with family and friends and the time has come to open a bottle of wine. The wine bottle has a cork seal with a plastic outer wrapper to protect the cork. Our Swiss Army Knife becomes useful to help us open the bottle. We unfold the small knife blade attachment and use it to cut away the plastic outer wrapper protecting the cork. Once completed, the small knife blade gets folded back to its closed position and the corkscrew attachment is opened to assist us in removing the cork from the bottle. We grip the handle of the Swiss Army Knife the same way for each of these attachments.

Object-oriented programming offers us something similar to the design of a Swiss Army Knife. We can define object-oriented classes to correspond to each one of the Swiss Army Knife tool attachments, and indicate that each one implements the same interface . This interface then acts as the handle by which we can grip and manipulate the corresponding tool attachment.

A Family of Interchangeable Features

The Strategy design pattern encapsulates a set of features that all offer the same interface for their access. Strategy is categorized by GoF with a behavioral purpose and an object scope. The intent behind this design pattern is the following:

  • Define a family of algorithms , encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. 1

Strategy makes use of these participants2 working in collaboration with each other:

  1. Strategy: Declares an interface common to all supported algorithms . Context uses this interface to call the algorithm defined by a ConcreteStrategy .

  2. ConcreteStrategy: Implements the algorithm using the Strategy interface.

  3. Context: Is configured with a ConcreteStrategy object. Maintains a reference to a Strategy object. May define an interface that lets Strategy access its data.

The UML class diagram for Strategy is shown in Figure 12-1.

A447555_1_En_12_Fig1_HTML.jpg
Figure 12-1. UML class diagram for the Strategy design pattern

Notice that the Context participant does not access any ConcreteStrategy participant directly, but does so through the interface provided by the Strategy participant.

The definitive word of the intent is interchangeable. By providing clients an interface by which to access the implementations of its methods, each class of the family can be referenced through a corresponding interface reference variable. Furthermore, restricting the methods of each family class only to those it gains through the interface is what makes each class interchangeable with all other classes in the same family. Accessing any of the family classes through the interface using an interface reference variable constitutes the optimal way to access the class. Accordingly, a client will have no dependencies on any particular class in this family of classes. This allows us to adhere to one of the principles of reusable object-oriented design espoused by GoF :

  • Program to an interface, not an implementation.3

The definitive phrase of the intent is vary independently. Since access to one of the interchangeable classes of the family is best achieved via interface reference variables, then the classes that comprise the family members are not accessed directly by any clients. This leaves each of the classes in the family free to have their implementations changed however and whenever a developer sees fit. It removes the obstacle of searching for direct callers of the class to determine the impact any changes would have upon those callers. Since each class in the family implements the same interface, and only that interface, and as long as the interface doesn’t change, then the search for external callers is rendered unnecessary, thus simplifying the maintenance process.

The use of the Strategy design pattern illustrates an example of using class composition. In the UML diagram above, the context entity is shown to include both a private attribute named strategy and a public method named contextInterface. The relationship between the strategy entity and the private attribute of the context entity is depicted using an aggregation instance level relationship line. This means a strategy entity is among those objects composing the context entity. In effect, the context has a strategy, one that is determined and created during program execution.

To return to our Swiss Army Knife analogy, as long as a new foldable attachment can be properly fitted into a specific model, the attachment can be manipulated through the same handle as all of its other attachments.

The UML class diagram for the Strategy pattern adapted to the Swiss Army Knife is shown in Figure 12-2.

A447555_1_En_12_Fig2_HTML.jpg
Figure 12-2. UML class diagram for Strategy design pattern applied to the Swiss Army Knife

Here we see that a person can have a Swiss Army Knife. Furthermore, the person interacts with the Swiss Army Knife through the tool interface , enabling each of the tool attachments to be handled the same way. The person merely uses the tool attachment. The details associated with what use entails for each of the individual tool attachments are implemented in those respective concrete classes implementing the tool interface. Regardless of which tool happens to be open at the time, the person grasps the tool handle the same way for all of them.

Strategy in ABAP

Here is how we might implement the Strategy design pattern UML class diagram illustrated above into functioning ABAP code . The tool interface , shown in Listing 12-1, plays the role of the Strategy participant.

Listing 12-1. Tool Interface
interface tool.
  methods        : use_tool.
endinterface.

The following three classes play the roles of the ConcreteStrategy participants. As shown in Listing 12-2, the small_knife_blade_tool class definition indicates in its public section that it implements the tool interface and that has defined an alias for the use_tool method provided by the tool interface, while its private section defines the cut method. Its implementation shows public method use_tool invoking private method cut.

Listing 12-2. small_knife_blade Class
class small_knife_blade_tool definition.
  public section.
    interfaces   : tool.
    aliases      : use_tool for tool∼use_tool.
  private section.
    methods      : cut.
endclass.
class small_knife_blade_tool implementation.
  method use_tool.
    call method me->cut.
  endmethod.
  method cut.
    message 'cutting' type 'I'.
  endmethod.
endclass.

As shown in Listing 12-3, the bottle_cap_remover_tool class definition is defined similarly to the small_knife_blade_tool class except for the name of its private method. Its implementation shows public method use_tool invoking private method remove_bottle_cap.

Listing 12-3. bottle_cap_remover Class
class bottle_cap_remover_tool definition.
  public section.
    interfaces   : tool.
    aliases      : use_tool for tool∼use_tool.
  private section.
    methods      : remove_bottle_cap.
endclass.
class bottle_cap_remover_tool implementation.
  method use_tool.
    call method me->remove_bottle_cap.
  endmethod.
  method remove_bottle_cap.
    message 'removing bottle cap' type 'I'.
  endmethod.
endclass.

As shown in Listing 12-4, the magnifying_lens_tool class definition is also defined similarly to the small_knife_blade_tool class except for the name of its private method. Its implementation shows public method use_tool invoking private method magnify.

Listing 12-4. magnifying_lens_tool Class
class magnifying_lens_tool definition.
  public section.
    interfaces   : tool.
    aliases      : use_tool for tool∼use_tool.
  private section.
    methods      : magnify.
endclass.
class magnifying_lens_tool implementation.
  method use_tool.
    call method me->magnify.
  endmethod.
  method magnify.
    message 'magnifying' type 'I'. Strategy
  endmethod.
endclass.

As shown in Listing 12-5, the person class definition, playing the role of the Context participant, shows a private attribute swiss_army_knife defined as a reference to the tool interface . It also defines a public method called do_some_work. Also included here is a constructor method for providing a new person instance with a reference to a swiss_army_knife. The implementation for the constructor shows initializing the private attribute with the reference to the swiss_army_knife provided by the instantiator, meaning that at the completion of creating an instance of a person it will also have a reference to an instance of a swiss_army_knife. Its implementation for the public method do_some_work invokes method use_tool through its private attribute reference to the instance of a swiss_army_knife.

Listing 12-5. person Class
class person definition.
  public section.
    methods      : constructor
                     importing swiss_army_knife
                       type ref to tool
                 , do_some_work
                 .
  private section.
    data         : swiss_army_knife type ref to tool.
endclass.
class person implementation.
  method constructor.
    me->swiss_army_knife          = swiss_army_knife.
  endmethod.
  method do_some_work.
    call method me->swiss_army_knife->use_tool.
  endmethod.
endclass.

Finally, unrelated to the UML diagram but illustrating how the UML components would be used, a report program shown in Listing 12-6 defines a data field bartender as a reference to the person class and a data field bartender_tool as a reference to the tool interface . Subsequent processing shows creating an instance of a tool into the bartender_tool reference (specifically, one of class type bottle_cap_remover_tool), creating an instance of person into the bartender reference (passing the bartender_tool on the create statement), then finally invoking the do_some_work of the person instance through the bartender reference variable.

Listing 12-6. Report Program Snippet Using the Entities Defined Above
  o
  o
  data           : bartender            type ref to person
                 , bartender_tool       type ref to tool
                 .
  o
  o
  create object bartender_tool type bottle_cap_remover_tool.
  create object bartender
    exporting swiss_army_knife = bartender_tool.
  call method bartender->do_some_work.

When this report is executed we should expect to see “removing bottle cap” appear on the screen as an informational message.

Indeed, at some point we might expect a bar patron to approach the bartender with a request for a glass of wine, requiring the bartender to open a new bottle. So it is not too difficult for us to imagine a class defining a corkscrew tool also implementing the tool interface , such as shown in Listing 12-7.

Listing 12-7. corkscrew_tool Class
class corkscrew_tool definition.
  public section.
    interfaces   : tool.
    aliases      : use_tool for tool∼use_tool.
  private section.
    methods      : uncork_bottle.
endclass.
class corkscrew_tool implementation.
  method use_tool.
    call method me->uncork_bottle.
  endmethod.
  method uncork_bottle.
    message 'uncorking bottle' type 'I'.
  endmethod.
endclass.

Accordingly, we might expect something similar to the snippet of code in Listing 12-8 to be added to the report program to facilitate the request by a patron to the bartender for a glass of wine.

Listing 12-8. Report Program Snippet Using the New Class Defined in Listing 12-7
o
o
create object bartender_tool type corkscrew_tool.
create object bartender
  exporting swiss_army_knife = bartender_tool.
call method bartender->do_some_work.

Notice that the requests to open a bottle of beer or to open a bottle of wine both use the very same statement,

call method bartender->do_some_work.

but result in different behaviors depending on which attachment of the bartender's Swiss Army Knife is open.

With this additional code, now when this report is executed we should see the message “removing bottle cap” appear on the screen followed by the message “uncorking bottle.” It is through its abilities to invoke the behaviors of the tool interface for different classes implementing the tool interface and get a different result with each behavior that makes the Strategy design pattern so powerful.

Summary

In this chapter, we learned the benefits of accessing a class through an interface reference. We now are familiar with the way in which we can define a family of interchangeable classes where each family member implements the same interface, enabling us to decide during execution which class of the family is the most appropriate one to be used for the task at hand. The use of the Strategy design pattern enhances our ability to provide more flexible software designs because through its use we are able to apply maintenance changes to a class independently from the clients using it.

Strategy Exercises

Actually, there are no new exercise programs associated with this chapter since the Strategy design pattern has already been used with the exercise programs since Chapter 7, which covered interfaces. Refer to Chapter 9 of the associated functional and technical requirements documentation (see Appendix B) for more details.

Footnotes

1 GoF , p. 315.

2 GoF, p. 317.

3 GoF , p. 18.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset