ABAP Objects Design Patterns – Builder

By | April 8, 2013 | ABAP Objects, OO Design Patterns | 2,496 | 2

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.

Page Contents

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.

Like It? Share!!

Don't miss an Update

Naimesh Patel{245 articles}

I'm SAP ABAP Consultant for more than a decade. I like to experiment with ABAP especially OO. I have been SDN Top Contributor.
Follow :

Explore all of his 245 articles.

Load comments

2 Comments

  • marcin

    Hello Naimesh,

    Thanks for explaining us the concept of a Builder pattern. I believe this adheres to Gang of Four description of a Builder. Anyhow what I would personally improve this a bit by removing LIF_PIZZA interface and only use LCL_PIZZA itself. Why?

    I understand the build process like this:
    - abstract builder knows a recipe for bulding a pizza
    - it takes plain pizza (LCL_PIZZA) and creates it according to the recipe
    - concrete builder knows how to differantiate build for different pizza types i.e. VegPizzaBuilder knows recipe for Ver Pizza etc.

    So in my opinion (could be wrong) we don’t need to differantiate pizza itself. Only we must know how to create plain pizza and concrete builder do the rest of a job. We will probably never utilize LIF_PIZZA.

    On the other hand, I may imagine we want to variable pizza dough no matter the topping or sauce. In such a case I would keep LIF_PIZZA and implement it in ThinPizza and ThickPizza classes. Then I would create two new classes VegPizzaBuilderThin, VegPizzaBuilderThick and let the client choose the dough and pizza by passing concrete builder to the cook. I know the result would be the same, but here I see more justified presence of a LIF_PIZZA. I agree in the simplest case we don’t want to overwhelm the client with tens of builders, so probably the way you presented is the most efficient and preferable approach.

    Cheers
    Marcin

  • Hello Marcin,

    Nice to hear from you, after a long pause :)

    I agree that you as such don’t need LIF_PIZZA. But as a generic OO Rule – you always create an unified interface (either an interface or abstract class) which can be implemented by concrete classes to provide one more level of flexibility.

    In this example, LIF_PIZZA doesn’t add any additional value as we only have simple version on PizzaBuilder. As you pointed out, if we have complex version where each part is made of the smaller complex parts which are in turn build by another builder, you could definitely see the purpose of LIF_PIZZA.

Comments on this Post are now closed. If you have something important to share, you can always contact me.