© James E. McDonough 2017

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

21. Null Object Pattern

James E. McDonough

(1)Pennington, New Jersey, USA

The next stop on our voyage through the Design Patterns galaxy takes us to the Null Object design pattern , the first of two design patterns we’ll encounter that are not registered in the GoF catalog. We will find this design pattern useful in reducing conditional logic .

While using a program, a user may be able to issue commands for actions prior to having selected the type of object upon which those actions are applicable. Without having selected an object, the reference to the object is not yet bound to an actual object. We might find ourselves implementing conditional logic in the program to check whether or not an object is bound before attempting to use one of its methods to facilitate the action selected by the user.

The Placebo Effect

A null object is one defined to be a surrogate for another object, providing null implementations for all the behaviors of the object for which it is a surrogate. With a null object, we can dispense with the conditional logic in the program testing whether or not an actual object is bound to an object reference. Instead, we insure that a null object is bound to the object reference from the time the program begins executing until the time the user makes an object selection, which can then replace the null object. Any actions the user issues prior to selecting an object for those actions will be issued against the null object, which will do … nothing.

The Null Object design pattern is not covered by GoF. The intent behind this design pattern is the following:

  • Provide an object as a surrogate for the lack of an object of a given type. The Null Object pattern provides intelligent do-nothing behavior, hiding the details from its collaborators. 1

This pattern becomes useful in situations where we do not yet have available to us an object that can provide any actual “do” behaviors. Since the null object is designed to provide empty behaviors for every behavior available through an object for which it acts as a surrogate, an object reference can be bound to a null object during the initialization phase of the entity holding a reference to the object. This alleviates the need for the conditional logic to test for a bound reference; it will always be bound to some object.

The UML class diagram for the Strategy pattern adapted to the Swiss Army Knife we saw in a previous chapter is shown in Figure 21-1, this time using a null object to handle the cases where one of the various attachments has not yet been chosen.

A447555_1_En_21_Fig1_HTML.jpg
Figure 21-1. UML class diagram for the Strategy design pattern, expanded to include null object class noToolOpen

In this case, we instantiate an object of class person, a class that “has a” Swiss Army Knife as one of its attributes. Instead of placing conditional logic into the implementation of the doSomeWork method of the person class, testing whether or not there is a bound instance of a tool ready for use, a Swiss Army Knife instance is instantiated during the initialization of the person object, and it holds a reference to a noToolOpen object. If the doSomeWork method is then invoked prior to having created an instance of a specific tool of the Swiss Army Knife, the corresponding invocation of the useTool method results in no activity. In this way, there is always a bound reference to the SwissArmyKnife attribute upon which its public method useTool can be invoked, alleviating the need to include conditional logic throughout the code checking for the presence of a bound reference before attempting to invoke its methods.

Null Object in ABAP

Here is how we might implement the Null Object design pattern UML class diagram illustrated above in Figure 21-1 into functioning ABAP code. The following definitions for the interface tool and classes bottle_cap_remover_tool and magnifying_lens_tool, shown in Listing 21-1, were copied unchanged from Listings 12-1, 12-3, and 12-4 of the section describing the Strategy design pattern in Chapter 12.

Listing 21-1. Interface Tool and Classes bottle_cap_remover and magnifying_lens_tool
interface tool.
  methods        : use_tool.
endinterface.


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.


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'.
  endmethod.
endclass.

The no_tool_open class shown in Listing 21-2 represents a null object.

Listing 21-2. Class no_tool_open, Implemented as a Null Object
class no_tool_open definition.
  public section.
    interfaces   : tool.
    aliases      : use_tool for tool∼use_tool.
endclass.
class no_tool_open implementation.
  method use_tool.
  endmethod.
endclass.

Notice the implementation shown in Listing 21-2 for method use_tool is empty. Accordingly, should this object ever be instantiated and its use_tool method invoked, no action will occur.

The person class shown in Listing 21-3 also was copied from Listing 12-5 of the Strategy section in Chapter 12, but its constructor signature has been changed to make instantiating a corresponding Swiss Army Knife optional. Differences from Listing 12-5 are highlighted.

Listing 21-3. Class person, with Differences from Listing 12-5 Highlighted
class person definition.
  public section.
    methods      : constructor
                     importing swiss_army_knife
                       type ref to tool optional
                 , do_some_work
                 .
  private section.
    data         : swiss_army_knife type ref to tool.
endclass.
class person implementation.
  method constructor.
    if swiss_army_knife is supplied.
      me->swiss_army_knife        = swiss_army_knife.
    else.
      create object me->swiss_army_knife
        type no_tool_open.
    endif.
  endmethod.
  method do_some_work.
    call method me->swiss_army_knife->use_tool.
  endmethod.
endclass.

The report shown in Listing 21-4 instantiates a person object as a reference to a baby, a type of person we should expect to have no access to a Swiss Army Knife. Accordingly, the instantiation of the baby object omits the optional swiss_army_knife parameter applicable to its constructor, leaving the constructor method of the person class to create an instance of a null object for the Swiss Army Knife attribute of this person object.

Listing 21-4. Report That Creates an Instance of class Person and Then Invokes Its do_some_work Method Without First Invoking a Method to Select a Tool of the Swiss Army Knife
report.
  data           : baby type ref to person.
  o
  o
  create object baby.
  o
  o
  call method baby->do_some_work.

Notice that the create object statement in Listing 21-4 specifies no importing parameter for the baby object. As a consequence, the baby object is created with a Swiss Army Knife with no tool open due to the conditional check for a supplied parameter in the constructor method of the person class, which, as shown in Listing 21-3, is now marked optional. A call to method do_some_work of the baby instance, shown in Listing 21-4 as the final statement of the report, will result in no action taking place by the corresponding Swiss Army Knife instance.

Summary

In this chapter, we learned a way to avoid the necessity of providing conditional logic to check for the presence of a bound object reference, simplifying the logic and having a positive effect on maintenance efforts. The Null Object design pattern provides a way to create instances of classes that do nothing but can be used like any other class instance.

Null Object Exercises

Refer to Chapter 18 of the functional and technical requirements documentation (see Appendix B) for the accompanying ABAP exercise programs associated with this chapter. Take a break from reading the book at this point to reinforce what you have read by changing and executing the corresponding exercise programs. There is one exercise program associated with this chapter: ZOOT311A.

Footnotes

1 This definition is taken from www.oodesign.com/null-object-pattern.html .

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

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