Click here to Skip to main content
Click here to Skip to main content
Go to top

Builder Pattern

, 22 Jan 2013
Rate this:
Please Sign up or sign in to vote.
The idea behind the builder pattern is to abstract away the construction of an object so that many implementations can use the same builder.

This post will be about the Builder pattern which is a creational pattern.

The Purpose

The idea behind the builder pattern is to abstract away the construction of an object so that many implementations can use the same builder. This separates the construction logic of the desired class from it’s representation.

The Pattern

Here is a general UML diagram for this

Builder Pattern

So the object you are interested in creating is the class Product in this scenario. The class which you call to deal with this is the Director.

The Director keeps a member which implements the Builder interface and calls this in it’s create() method. This member is one of the ConcreteBuilder classes and has the logic needed for the creation of the specific Product you want.

This abstracts the logic needed to create different types of Product. The Product may also be an interface and each ConcreteBuilder may return a different type.

The Builder is typically set either with a function, where the Director class is responsible for the logic of the ConcreteBuilder creation, or by passing a ConcreteBuilder directly to the Director.

An Example Usage

This will use the example of building different types of vehicles. The code for this example is all contained in this file.

The Product here is a Vehicle which is defined as the following class.

#==============================================================================
class Vehicle(object):

    def __init__(self, type_name):
        self.type = type_name
        self.wheels = None
        self.doors = None
        self.seats = None

    def view(self):
        print(
            "This vehicle is a " +
            self.type +
            " with; " +
            str(self.wheels) +
            " wheels, " +
            str(self.doors) +
            " doors, and " +
            str(self.seats) +
            " seats."
            )

So different Vehicles can have different names, numbers of wheels doors and seats. The method view() will print a summery of what the Vehicle is.

The construction of instances of Vehicle will be handles by the ConcreteBuilder classes. These should derive from a Builder interface (abstract class) so here is the base class VehicleBuilder.

#==============================================================================
class VehicleBuilder(object):
    """
    An abstract builder class, for concrete builders to be derived from.
    """
    __metadata__ = abc.ABCMeta
    
    @abc.abstractmethod
    def make_wheels(self):
        raise

    @abc.abstractmethod
    def make_doors(self):
        raise

    @abc.abstractmethod
    def make_seats(self):
        raise

This uses the abc module just like the first version of PrimeFinder in my strategy pattern post.

So with this Builder there are three functions for setting up the Vehicle. For the ConcreteBuilders there is a CarBuilder and a BikeBuilder, both of which inherit from VehicleBuilder. Here are the implementations of these classes.

#==============================================================================
class CarBuilder(VehicleBuilder):

    def __init__(self):
        self.vehicle = Vehicle("Car ")

    def make_wheels(self):
        self.vehicle.wheels = 4

    def make_doors(self):
        self.vehicle.doors = 3

    def make_seats(self):
        self.vehicle.seats = 5

#==============================================================================
class BikeBuilder(VehicleBuilder):

    def __init__(self):
        self.vehicle = Vehicle("Bike")

    def make_wheels(self):
        self.vehicle.wheels = 2

    def make_doors(self):
        self.vehicle.doors = 0

    def make_seats(self):
        self.vehicle.seats = 2

The only logic in these is the creation of the vehicle object and setting the properties on it. Now to use these we need a Director class to call. For this example the Director is called VehicleManufacturer.

#==============================================================================
class VehicleManufacturer(object):
    """
    The director class, this will keep a concrete builder.
    """
    
    def __init__(self):
        self.builder = None

    def create(self):
        """ 
        Creates and returns a Vehicle using self.builder
        Precondition: not self.builder is None
        """
        assert not self.builder is None, "No defined builder"
        self.builder.make_wheels()
        self.builder.make_doors()
        self.builder.make_seats()
        return self.builder.vehicle

VehicleManufacturer has a create() function which contains the calling code used with the Builder. However as you can see from the docstring and the code this has a precondition of self.builder being set. This means that if you have not given the Director a ConcreteBuilder to use, it cannot create a Vehicle.

So this class is called like so.

#==============================================================================
if (__name__ == "__main__"):
    manufacturer = VehicleManufacturer()
    
    manufacturer.builder = CarBuilder()
    car = manufacturer.create()
    car.view()

    manufacturer.builder = BikeBuilder()
    bike = manufacturer.create()
    bike.view()

The calling code uses one VehicleManufacturer to build both a car and a bike. The output of this code is given below.

This vehicle is a Car  with; 4 wheels, 3 doors, and 5 seats.
This vehicle is a Bike with; 2 wheels, 0 doors, and 2 seats.

The specific UML for this example is this.

Specific Builder Pattern

All of the code for the design patterns can be found here. Thanks for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

David Corne
Software Developer
United Kingdom United Kingdom
I am a C++ developer with a strong interest in Python, C#, and Qt. I work on a native C++ application which uses COM to call C# in order to use a WPF GUI.
 
While I develop an application using WPF exclusivly for windows, I am a big linux user. My favourite distro at the moment is Linux Mint, and I love the delights of the command line,.
 
If you've read something of mine and you enjoyed it, check out my blog.
 
I am also active on various other sites, listed below.

Coding Sites

  • BitBucket where I keep the majority of my projects.
  • GitHub where I have a few older projects. This includes my current long term project, I'm writing a book about design patterns in python. Find the repository here and blog posts about individual patterns here
  • Stackoverflow I'm not too active on stackoverflow, I'm more of a listener.
  • coderwall and coderbits two profile compilation websites.

Social Sites

Follow on   Twitter   Google+

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 4 PinmemberJerry OLoughlin22-Feb-13 6:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 22 Jan 2013
Article Copyright 2013 by David Corne
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid