Hope this page might elucidate this pattern in a bit explicit manner.

Pattern overview

Pattern Name and Classification

The builder pattern is an object creation software design pattern. Unlike the abstract factory pattern and the factory method pattern whose intention is to enable polymorphism, the intention of the builder pattern is to find a solution to the telescoping constructor anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once.

Intent

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Also Known As

Other names for the pattern.

Motivation (Forces)

The main premise for design is an excessive number of constructors.

Applicability

Builder often builds a Composite. Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. Sometimes creational patterns are complementary: Builder can use one of the other patterns to implement which components are built.

Structure

A graphical representation of the pattern. Class diagrams and Interaction diagrams may be used for this purpose.

Participants

Builder

specifies an abstract interface for creating parts of a Product object.

ConcreteBuilder

  • constructs and assembles parts of the product by implementing the Builder interface.
  • defines and keeps track of the representation it creates.
  • provides an interface for retrieving the product.

Director

constructs an object using the Builder interface.

Product

  • represents the complex object under construction. ConcreteBuilder builds the product's internal representation and defines the process by which it's assembled.
  • includes classes that define the constituent parts, including interfaces for assembling the parts into the final result.

Collaboration

  • The client creates the Director object and configures it with the desired Builder object.
  • Director notifies the builder whenever a part of the product should be built.
  • Builder handles requests from the director and adds parts to the product.
  • The client retrieves the product from the builder.

Implementation

A description of an implementation of the pattern; the solution part of the pattern.

Consequences

A description of the results, side effects, and trade offs caused by using the pattern.

Known Uses

Examples of real usages of the pattern.

Related Patterns

Other patterns that have some relationship with the pattern; discussion of the differences between the pattern and similar patterns.

Samples

For educational purposes it would be priceless to look at the working code sample. Exactly to achieve a stunning clarity it might be reasonable to compose a test suite for testing the pattern features and dispose it nearby the pattern source code.

SkyLark builder

Composes some particular model on demand.

Pattern code Test suite
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A SkyLark builder
"""


class Car(object):
    """Product"""

    def __init__(self):
        self.model = None
        self.tires = None
        self.engine = None

    def __str__(self):
        return '{} | {} | {}'.format(
            self.model, self.tires,
            self.engine)


class Director(object):
    """Director"""

    def __init__(self, builder):
        self._builder = builder

    def construct_car(self):
        pass

    def get_car(self):
        pass


class Builder(object):
    """Abstract Builder"""

    def __init__(self):
        self.car = None

    def create_new_car(self):
        self.car = Car()


class SkyLarkBuilder(Builder):
    """Concrete Builder --> provides 
    parts and tools to work on the 
    parts"""

    def add_model(self):
        self.car.model = "Skylark"

    def add_tires(self):
        self.car.tires = "Regular tires"
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
An attempt to illustrate how it works
"""
import unittest


class TestSimpleBehavior(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

A premises builder

Pattern code Test suite
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A dwelling builder
"""


class Director(object):

    def __init__(self):
        self.builder = None

    def construct_building(self):
        self.builder.new_building()
        self.builder.build_floor()
        self.builder.build_size()

    def get_building(self):
        return self.builder.building


class Builder(object):
    """
    Abstract Builder
    """

    def __init__(self):
        self.building = None

    def new_building(self):
        self.building = Building()

    def build_floor(self):
        raise NotImplementedError

    def build_size(self):
        raise NotImplementedError


class BuilderHouse(Builder):
    """Concrete Builder"""

    def build_floor(self):
        self.building.floor = 'One'

    def build_size(self):
        self.building.size = 'Big'


class BuilderFlat(Builder):

    def build_floor(self):
        self.building.floor = 'More than One'

    def build_size(self):
        self.building.size = 'Small'


class Building(object):
    """Product"""

    def __init__(self):
        self.floor = None
        self.size = None

    def __repr__(self):
        return 'Floor: {0.floor} | Size: {0.size}'.format(self)

director = Director()
director.builder = BuilderHouse()
director.construct_building()
building = director.get_building()
print(building)
director.builder = BuilderFlat()
director.construct_building()
building = director.get_building()
print(building)
Floor: One | Size: Big
Floor: More than One | Size: Small
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
An attempt to illustrate how it works
"""
import unittest


class TestSimpleBehavior(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass


blog comments powered by Disqus

Published

19 March 2017

Categories

literate programming emacs Python3

Tags