Builder design pattern wrapped with Python3
Table of Contents
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