Builder
"Separate the construction of a complex object from its representation so that the same construction process can create different representations." — Gang of Four, Design Patterns: Elements of Reusable Object-Oriented Software, 1994.
Có bao giờ bạn nhìn vào một constructor với 20 tham số và tự hỏi: "Cái quái gì đang xảy ra ở đây vậy?" Tôi thì có — và tôi ghét nó.
Builder thuộc nhóm Creational Patterns, tách quá trình xây dựng một object phức tạp ra khỏi biểu diễn của nó. Pattern này cho phép cùng một quy trình xây dựng (construction process) tạo ra nhiều biểu diễn (representations) khác nhau. Điểm mạnh cốt lõi của Builder nằm ở chỗ nó kiểm soát được từng bước của quá trình xây dựng — điều mà Factory Method và Abstract Factory không làm được.
Bài toán chi tiết
Giả sử bạn đang xây dựng một hệ thống tạo báo cáo tài chính tự động cho một ngân hàng đầu tư. Mỗi ngày, hệ thống phải sinh ra hàng trăm báo cáo khác nhau: báo cáo giao dịch nội bộ, báo cáo cho khách hàng, báo cáo cho cơ quan thuế, và báo cáo kiểm toán nội bộ. Mỗi loại báo cáo có cấu trúc phức tạp với nhiều phần: header (logo, tên báo cáo, ngày giờ, mã tham chiếu), summary section (tổng quan tài chính, con số chính, các KPI), transaction table (danh sách giao dịch), charts section (biểu đồ phân tích), và footer (chữ ký số, disclaimer, QR code).
Mỗi báo cáo có thể được xuất ra nhiều định dạng: PDF (cho khách hàng), Excel (cho nội bộ), HTML (cho web dashboard), và JSON (cho API). Mỗi định dạng có cách render khác nhau — PDF cần layout chính xác từng pixel, Excel cần cell references và formulas, HTML cần CSS và responsive design.
Cách tiếp cận ngây thơ ban đầu là dùng một constructor khổng lồ với 20+ tham số. Điều này dẫn đến telescoping constructor — người dùng phải nhớ thứ tự và ý nghĩa của từng tham số. Object có thể được tạo với state không hợp lệ (thiếu header, thiếu footer). Cùng loại báo cáo nhưng khác format phải viết lại toàn bộ constructor.
Kinh nghiệm của tôi: Mỗi khi thấy một constructor có hơn 5 tham số, đó là dấu hiệu bạn đang cần Builder.