Creational Patterns II: Abstract Factory & Builder
Design Patterns
Chapter 3 · Creational Patterns II: Abstract Factory & Builder
Chapter 2's Factory Method delegated creating one object to a subclass. This chapter covers two bigger jobs: keeping a whole family of related objects consistent (Abstract Factory), and constructing one genuinely complex object safely, step by step (Builder) — both demonstrated by reproducing the real bug each one exists to prevent.
Abstract Factory: Keeping a Family of Objects Consistent
A UI toolkit needs a button and a checkbox that always match — a light-theme button should never end up next to a dark-theme checkbox. Abstract Factory provides one factory per family, so requesting any piece of a family automatically gets the matching version of every other piece.
build_ui(LightThemeFactory()) returns a LightButton and a LightCheckbox — confirmed by type, not just by name. build_ui(DarkThemeFactory()) returns a DarkButton and a DarkCheckbox. Every single component produced through a given factory belongs to the same family, every time.
LightButton() paired with DarkCheckbox(). This runs without any error and compiles/executes perfectly — 'Light button (white bg, black text)' next to 'Dark checkbox (black bg, white check)' — a genuinely mismatched, jarring UI, produced by code that looks completely reasonable at a glance. Abstract Factory's real value is structural: going through build_ui(factory) makes this specific mistake impossible to write, not just discouraged by convention.
Builder: Constructing a Complex Object Safely
A class with many optional parameters — a computer configuration, say — tempts a "telescoping constructor": one big constructor accepting everything positionally.
cpu='i7', ram='16GB', storage='512GB SSD', case_color='white', a caller writes Computer('i7', '16GB', '512GB SSD', 'white') — a completely natural-looking mistake, since 'white' lands in the fourth positional slot, which is actually gpu, not case_color. The result: gpu='white' (nonsensical — a GPU with no such model) and case_color silently stays at its default, 'black' — exactly the opposite of what was intended, with no error raised anywhere.
Builder replaces positional parameters with named, chained method calls — each step says exactly what it's setting:
ComputerBuilder().set_cpu('i7').set_ram('16GB').set_storage('512GB SSD').set_case_color('white').build() produces exactly the intended object: gpu=None (correctly left unset — the step was never called) and case_color='white' (correctly set) — the exact opposite of the telescoping constructor's own mistaken result, for the identical underlying intent. There is no positional slot to get wrong, because every step names the field it sets.
Where This Connects
| This chapter's finding | What it sets up |
|---|---|
| Abstract Factory structurally preventing a mixed-family bug | The same "make the wrong thing impossible to write, not just discouraged" idea reappears in Chapter 5's Composite |
| A real, reproduced telescoping-constructor bug, fixed by Builder | A concrete case study for Clean Code, SOLID & Refactoring's own material on function/constructor parameter design |
| Both patterns building on Chapter 2's Factory Method | Chapter 4's structural patterns shift focus from *creating* objects to *composing* already-created ones |
Hands-On Exercises
Using this chapter's own Abstract Factory pattern, add a third family member — create_slider() — to UIFactory, LightThemeFactory, and DarkThemeFactory, with matching LightSlider/DarkSlider classes. Verify build_ui()-style code produces a consistently-themed slider alongside the button and checkbox.
Using this chapter's own telescoping-constructor bug, identify exactly which named parameter each of the four positional arguments in Computer('i7', '16GB', '512GB SSD', 'white') actually binds to, and explain why the resulting object doesn't raise any error despite being wrong.
Using this chapter's own two patterns, explain what specific kind of bug each one prevents — Abstract Factory vs. Builder — and why a class with only a single required parameter and no optional ones would need neither pattern.
📄 View solutionChapter 3 Quick Reference
- Abstract Factory: one factory produces a whole family of related objects — verified consistent by type (
LightButton+LightCheckbox,DarkButton+DarkCheckbox) - Verified directly: bypassing the factory makes mixing families (
LightButton+DarkCheckbox) trivially possible with no error — exactly what Abstract Factory structurally prevents - Builder: named, chained construction steps replace a positional "telescoping constructor"
- Verified directly: a realistic positional-argument mistake silently set
gpu='white'instead ofcase_color='white', with no error raised — the Builder version produced the correct result with no possible mix-up - Next chapter: Structural Patterns I — Adapter and Facade, shifting from creating objects to composing already-created ones