Gyan Factory

Gyan Factory
SAP Technical Project Support

Tuesday, February 16, 2016

ABAP Objects Design Patterns – Builder

Builder is another Design Patterns in Object Oriented, to hide complex object building from the client. Lets check out it design and its implemented in OO ABAP.

What is Builder Design Pattern?

By definition, Separate the complex object creation from its representation. This would allow you to reuse the same construction process to create different representations of the same object. In other words, Builder creates object by following step by step process. It also decouples the way objects are created so the same setup can create different representation of the object.
You might think how it is different than, we previously discussed Abstract Factory Design Pattern? Abstract factory generally returns the object immediately where as Builder has complex step-by-step process to build the object for you. Builder first instantiates the objects and follows through all the necessary steps to make sure object is ready for consumption.

Participants

These are the different participants used in builder design pattern:
  • Product – This is the object which would be returned from the Builder. This object would be complex and would need a step-by-step process of assembly for creating the product. This complexity of building the object is hidden and decoupled from the clients.
  • Builder – Provides a unified interface for building the objects
  • Concrete Builder – Implements the Builder to provide the concrete object. Concrete Builder also keeps track of the representation of the object.
  • Director – Calls the Builder to get the concrete object

Demo

Few days back, one of the reader Marcin Pciak has posted a blog on SCN OOP geek journal – separate responsibilities. In this implementation, he used the Builder design pattern to build the pattern object. In one of my comment, I mentioned a demo application – Pizza builder. Lets take that as a reference for this demo and try to elaborate it in details.

UML

UML of the class relations:
In here, I have these classes. Compare them with the Participants listed in Participants section.
  • LIF_PIZZA & LCL_PIZZA – Complex objects which needs step-by-step assembly which represents final object
  • PIZZABUILDER – Abstract builder with unified interface to create new PIZZA object following the steps
  • VEGPIZZABUILDER & CHEESEPIZZABUILDER – Implements the Abstract builder. These concrete classes would do the logic to set the proper attributes on the Final Product which is reference to LIF_PIZZA.
  • COOK – Director who calls the Builders to build the Pizza. Cook performs the steps to build the final product.
So, when a new pizza type is required, you would need to create concrete class like VegPizzaBuilder in order to implement the object creation steps.

Code Lines

Code lines for Builder Design Patterns Demo

Builder Design Pattern Demo

 
*&---------------------------------------------------------------------*
*& Purpose - ABAP Objects Builder Design Patterns
*& Author  - Naimesh Patel
*& URL     - http://zevolving.com/?p=2109
*&---------------------------------------------------------------------*
REPORT ZNP_DP_BUILDER.
*
* Product
INTERFACE lif_pizza.
  DATA: dough TYPE STRING,
        sauce TYPE STRING,
        topping TYPE STRING.
ENDINTERFACE.                    "lif_pizza
*
CLASS lcl_pizza DEFINITION.
  PUBLIC SECTION.
    INTERFACES: lif_pizza.
ENDCLASS.                    "lcl_pizza DEFINITION
* abstract builder
CLASS pizzabuilder DEFINITION ABSTRACT.
  PUBLIC SECTION.
    METHODS: createnewpizza
      RETURNING VALUE(ro_pizza) TYPE REF TO lif_pizza.
    METHODS: builddough ABSTRACT,
             buildsauce ABSTRACT,
       buildtopping ABSTRACT.
  PROTECTED SECTION.
    DATA: pizza TYPE REF TO lif_pizza.
ENDCLASS.                    "pizzabuilder DEFINITION
*
CLASS pizzabuilder IMPLEMENTATION.
  METHOD createnewpizza.
    CREATE OBJECT pizza TYPE lcl_pizza.
    ro_pizza = pizza.
  ENDMETHOD.                    "createnewpizza
ENDCLASS.                    "pizzabuilder IMPLEMENTATION
*
* concreate builder - Veggie Pizza
CLASS vegpizzabuilder DEFINITION INHERITING FROM pizzabuilder.
  PUBLIC SECTION.
    METHODS: builddough REDEFINITION,
             buildsauce REDEFINITION,
             buildtopping REDEFINITION.
ENDCLASS.                    "vegpizzabuilder DEFINITION
*
CLASS vegpizzabuilder IMPLEMENTATION.
  METHOD builddough.
    pizza->dough = 'Thin Crust'.
  ENDMETHOD.                    "builddough
  METHOD buildsauce.
    pizza->sauce = 'Mild'.
  ENDMETHOD.                    "buildsauce
  METHOD buildtopping.
    pizza->topping = 'Olives, Pineapples, Jalapenos'.
  ENDMETHOD.                    "buildtopping
ENDCLASS.                    "vegpizzabuilder IMPLEMENTATION
*
* concrete builder - Cheese Pizza
CLASS cheesepizzabuilder DEFINITION INHERITING FROM pizzabuilder.
  PUBLIC SECTION.
    METHODS: builddough REDEFINITION,
             buildsauce REDEFINITION,
             buildtopping REDEFINITION.
ENDCLASS.                    "cheesepizzabuilder DEFINITION
*
CLASS cheesepizzabuilder IMPLEMENTATION.
  METHOD builddough.
    pizza->dough = 'Thick Crust'.
  ENDMETHOD.                    "builddough
  METHOD buildsauce.
    pizza->sauce = 'Mild Hot'.
  ENDMETHOD.                    "buildsauce
  METHOD buildtopping.
    pizza->topping = 'Cheese, Cheese, Cheese, more Cheese'.
  ENDMETHOD.                    "buildtopping
ENDCLASS.                    "cheesepizzabuilder IMPLEMENTATION
*
* Director
CLASS cook DEFINITION.
  PUBLIC SECTION.
    METHODS: constructpizza
      IMPORTING io_builder TYPE REF TO pizzabuilder
      RETURNING VALUE(ro_pizza) TYPE REF TO lif_pizza.
  PRIVATE SECTION.
    DATA: pizzabuilder TYPE REF TO pizzabuilder.
ENDCLASS.                    "cook DEFINITION
*
CLASS cook IMPLEMENTATION.
  METHOD constructpizza.
    pizzabuilder = io_builder.
    ro_pizza = pizzabuilder->createnewpizza( ).
    pizzabuilder->builddough( ).
    pizzabuilder->buildsauce( ).
    pizzabuilder->buildtopping( ).
  ENDMETHOD.                    "constructpizza
ENDCLASS.                    "cook IMPLEMENTATION
*
START-OF-SELECTION.
  DATA: o_cook TYPE REF TO cook,
        o_pizzabuilder TYPE REF TO pizzabuilder,
        o_pizza TYPE REF TO lif_pizza.
  CREATE OBJECT o_cook.
*
  "first pizza - Veggie
  CREATE OBJECT o_pizzabuilder TYPE vegpizzabuilder.
  o_pizza = o_cook->constructpizza( o_pizzabuilder ).
  " Just to understand what values are there
  WRITE: / o_pizza->dough, o_pizza->sauce, o_pizza->topping.
*
  "Second pizza - Cheese Lovers
  CREATE OBJECT o_pizzabuilder TYPE cheesepizzabuilder.
  o_pizza = o_cook->constructpizza( o_pizzabuilder ).
  WRITE: / o_pizza->dough, o_pizza->sauce, o_pizza->topping.
 

Have you used Builder DP?

Share you comments and experience while working/using builder design patterns.

No comments:

Post a Comment