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.
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.