Chương 8 — Builder Pattern

Builder pattern — code thực tế: sandwich builder

Bài toán: xây dựng sandwich

Hai loại sandwich với quy trình tương tự nhưng ingredients khác nhau:

  • Veggie Sandwich: Wheat bread + Lettuce + Tomato + Cucumber
  • Ham Sandwich: White bread + Ham + Cheese + Mayonnaise

Triển khai

Key idea 1: Core class — Sandwich

class Sandwich:
    def __init__(self):
        self.ingredients = []

    def add_ingredient(self, ingredient: str):
        self.ingredients.append(ingredient)

    def display(self) -> str:
        return "Sandwich: " + ", ".join(self.ingredients)

Key idea 2: Abstract Builder

from abc import ABC, abstractmethod

class SandwichBuilder(ABC):
    def __init__(self):
        self._sandwich = None

    def create_new_sandwich(self):
        self._sandwich = Sandwich()

    def get_result(self) -> Sandwich:
        return self._sandwich

    @abstractmethod
    def add_bread(self):
        pass

    @abstractmethod
    def add_filling(self):
        pass

Key idea 3: Concrete Builders

class VeggieSandwichBuilder(SandwichBuilder):
    def add_bread(self):
        self._sandwich.add_ingredient("Wheat bread")

    def add_filling(self):
        self._sandwich.add_ingredient("Lettuce")
        self._sandwich.add_ingredient("Tomato")
        self._sandwich.add_ingredient("Cucumber")

class HamSandwichBuilder(SandwichBuilder):
    def add_bread(self):
        self._sandwich.add_ingredient("White bread")

    def add_filling(self):
        self._sandwich.add_ingredient("Ham")
        self._sandwich.add_ingredient("Cheese")
        self._sandwich.add_ingredient("Mayonnaise")

Key idea 4: Director

class SandwichDirector:
    def __init__(self, builder: SandwichBuilder):
        self._builder = builder

    def change_builder(self, builder: SandwichBuilder):
        self._builder = builder

    def build_sandwich(self) -> Sandwich:
        self._builder.create_new_sandwich()
        self._builder.add_bread()
        self._builder.add_filling()
        return self._builder.get_result()

Sử dụng

Key idea 5: Client code cực kỳ đơn giản

# Bước 1: chọn builder
veggie_builder = VeggieSandwichBuilder()
director = SandwichDirector(veggie_builder)

# Bước 2: director tự làm mọi thứ
veggie_sandwich = director.build_sandwich()
print(veggie_sandwich.display())
# Sandwich: wheat bread, lettuce, tomato, cucumber

# Chuyển sang ham sandwich
director.change_builder(HamSandwichBuilder())
ham_sandwich = director.build_sandwich()
print(ham_sandwich.display())
# Sandwich: white bread, ham, cheese, mayonnaise

Key idea 6: Sequence diagram

Client          Director             VeggieSandwichBuilder
  │                │                         │
  │─ tạo Builder ─────────────────────────►│
  │─ tạo Director ─►│                       │
  │                  │                       │
  │─ build_sandwich()►│                     │
  │                  │─ create_new_sandwich()►│ (tạo Sandwich trống)
  │                  │─ add_bread() ─────────►│ (thêm Wheat bread)
  │                  │─ add_filling() ────────►│ (thêm Lettuce, Tomato, Cucumber)
  │                  │─ get_result() ──────────►│
  │◄──────────── Sandwich ───────────────────-│

Client chỉ cần: chọn builder + gọi director. Toàn bộ quá trình phức tạp được ẩn bên trong.

Đăng ký nhận Newsletter
Cập nhật bài viết mới nhất!