|
1 | 1 | # The Builder Pattern (Creational) |
2 | 2 |
|
3 | | -## Intent |
| 3 | +## Purpose |
4 | 4 |
|
5 | | -The Builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. It allows constructing complex objects step by step. |
| 5 | +The Builder pattern helps you construct complex objects step by step. It separates the construction process from the final product, making it easier to create different versions or configurations of the same type of object. |
6 | 6 |
|
7 | | -## Problem It Solves |
| 7 | +## The Problem It Solves |
8 | 8 |
|
9 | | -Imagine you are building a complex house, say with multiple rooms and furniture. You don't want to build everything at once because it can take forever and your budget is tight. Instead, you start with the foundation (maybe just the basement), then gradually add more as you need them. This process of constructing an object step by step is what the Builder pattern solves for. |
| 9 | +Sometimes an object is too complex to create in one step—like building a house with a foundation, walls, windows, and furniture. You might want different versions of the house, such as a basic layout or a luxury model. The Builder pattern lets you construct such objects gradually, using a consistent process, while still allowing flexibility in the final result. |
10 | 10 |
|
11 | 11 | ## When to Use It |
12 | 12 |
|
13 | | -The Builder pattern should be used when: |
| 13 | +Use the Builder pattern when: |
14 | 14 |
|
15 | | -1. You want your code to be able to create different representations of some product (for example, stone and wooden houses). |
16 | | -2. The construction process must allow different representations for the product that are implemented in various subclasses. |
17 | | -3. You need a simple interface to create complex objects. |
| 15 | +* You need to build complex objects with many parts. |
| 16 | +* You want to reuse the same construction process for different representations. |
| 17 | +* You want to isolate the construction logic from the actual product. |
18 | 18 |
|
19 | 19 | ## When NOT to Use It |
20 | 20 |
|
21 | | -The Builder pattern is not suitable when: |
| 21 | +Avoid this pattern if: |
22 | 22 |
|
23 | | -1. The object creation algorithm can be defined once and does not get changed often. |
24 | | -2. The client code should be simplified, without being overly complicated by the builder pattern. |
25 | | -3. You need a simple interface that creates only complex objects. |
| 23 | +* The object is simple and doesn’t require step-by-step construction. |
| 24 | +* You only ever need one version of the object, and its structure rarely changes. |
| 25 | +* Adding builders introduces unnecessary complexity for your use case. |
26 | 26 |
|
27 | 27 | ## How It Works |
28 | 28 |
|
29 | | -The Builder pattern works with four roles: Product, Builder, Director, and Client. |
| 29 | +The pattern has four key components: |
30 | 30 |
|
31 | | -1. **Product**: This is the object we are building. In our house example, it's the entire house. |
32 | | -2. **Builder**: This defines an interface for creating parts of a product. In our house example, this could be adding rooms or furniture to the house. |
33 | | -3. **Director**: This constructs an object using the Builder interface. It knows what part to build and in which order. In our house example, it would decide when to start building the basement first before moving on to add rooms later. |
34 | | -4. **Client**: The client is responsible for creating a builder object, setting its properties, and running the construction process. |
| 31 | +1. **Product** – The final object being built (e.g., a house). |
| 32 | +2. **Builder** – Defines methods to build each part of the product (e.g., walls, windows). |
| 33 | +3. **ConcreteBuilder** – Implements the builder’s steps to build and assemble parts of the product. |
| 34 | +4. **Director** – Controls the construction process and calls builder methods in a specific order. |
| 35 | + |
| 36 | +The **Client** sets up the builder and director, then triggers the construction. |
35 | 37 |
|
36 | 38 | ## Real-World Analogy |
37 | 39 |
|
38 | | -Think of the Builder pattern as a blueprint for your house. You start with the foundation (reset), then gradually add more components like walls, doors, windows, etc., one by one. The director is like a builder guide who knows exactly when to build each part and in what order. |
| 40 | +Think of building a house. You use a blueprint (the builder interface), hire a contractor (the concrete builder), and follow a schedule (the director) to build it step by step. The builder adds pieces like the foundation, walls, and roof. The director decides what to build first and when. |
39 | 41 |
|
40 | 42 | ## Simplified Example |
41 | 43 |
|
42 | | -Here's a simplified example of how you might use it: |
43 | | - |
44 | 44 | ```python |
| 45 | +# Builder interface |
| 46 | +class Builder(ABC): |
| 47 | + @abstractmethod |
| 48 | + def build_part_a(self): pass |
| 49 | + @abstractmethod |
| 50 | + def build_part_b(self): pass |
| 51 | + @abstractmethod |
| 52 | + def get_product(self): pass |
| 53 | + |
| 54 | +# Concrete builder |
| 55 | +class ConcreteBuilder(Builder): |
| 56 | + def __init__(self): |
| 57 | + self.reset() |
| 58 | + |
| 59 | + def reset(self): |
| 60 | + self._product = Product() |
| 61 | + |
| 62 | + def build_part_a(self): |
| 63 | + self._product.add("PartA") |
| 64 | + |
| 65 | + def build_part_b(self): |
| 66 | + self._product.add("PartB") |
| 67 | + |
| 68 | + def get_product(self): |
| 69 | + product = self._product |
| 70 | + self.reset() |
| 71 | + return product |
| 72 | + |
| 73 | +# Product |
| 74 | +class Product: |
| 75 | + def __init__(self): |
| 76 | + self.parts = [] |
| 77 | + |
| 78 | + def add(self, part): |
| 79 | + self.parts.append(part) |
| 80 | + |
| 81 | + def list_parts(self): |
| 82 | + return ", ".join(self.parts) |
| 83 | + |
| 84 | +# Director |
| 85 | +class Director: |
| 86 | + def __init__(self, builder: Builder): |
| 87 | + self._builder = builder |
| 88 | + |
| 89 | + def build_minimal_viable_product(self): |
| 90 | + self._builder.build_part_a() |
| 91 | + |
| 92 | + def build_full_featured_product(self): |
| 93 | + self._builder.build_part_a() |
| 94 | + self._builder.build_part_b() |
| 95 | + |
| 96 | +# Example usage |
45 | 97 | builder = ConcreteBuilder() |
46 | 98 | director = Director(builder) |
47 | 99 |
|
48 | | -director.build_minimal_viable_product() # Builds only part A |
49 | | -print("Minimal product:", builder.get_product().list_parts()) |
| 100 | +director.build_minimal_viable_product() |
| 101 | +print("Minimal product:", builder.get_product().list_parts()) |
50 | 102 |
|
51 | | -director.build_full_featured_product() # Builds parts A and B |
| 103 | +director.build_full_featured_product() |
52 | 104 | print("Full product:", builder.get_product().list_parts()) |
53 | 105 | ``` |
54 | 106 |
|
55 | | -In this example, `ConcreteBuilder` is the Builder that knows how to build a complex object (the house), `Director` guides the construction process by calling the appropriate building steps in sequence, and the client code creates a ConcreteBuilder object, sets its properties, and runs the construction process. |
| 107 | +### Output |
| 108 | + |
| 109 | +```text |
| 110 | +Minimal product: PartA |
| 111 | +Full product: PartA, PartB |
| 112 | +``` |
56 | 113 |
|
57 | | -## See Also |
| 114 | +## Learn More |
58 | 115 |
|
59 | | -You can find more details about this pattern [here](https://github.com/taggedzi/python-design-pattern-rag/blob/main/patterns/creational/builder.py). |
| 116 | +For a full implementation and examples, check: |
| 117 | +[Builder Pattern on GitHub](https://github.com/taggedzi/python-design-pattern-rag/blob/main/patterns/creational/builder.py) |
0 commit comments