Builder
Giới thiệu
Builder Pattern là một Creational Design Pattern cho phép xây dựng đối tượng phức tạp bằng cách sử dụng các đối tượng riêng biệt đại diện cho từng bộ phận cấu thành.
Builder Pattern tách rời quá trình khởi tạo đối tượng phức tạp khỏi các đại diện của nó. Điều này cho phép cùng một quá trình xây dựng có thể tạo ra nhiều biểu diễn khác nhau của đối tượng.
Mục đích: Builder Pattern được sử dụng để tách rời quá trình khởi tạo đối tượng phức tạp khỏi các đại diện của nó, giúp đạt được những lợi ích sau:
Tăng tính linh hoạt trong khởi tạo đối tượng phức tạp
Dễ dàng thay đổi cách khởi tạo đối tượng.
Hỗ trợ tạo nhiều biểu diễn khác nhau của đối tượng.
Đơn giản hóa việc test và debug.
Builder Pattern tách rời quá trình xây dựng đối tượng phức tạp thành nhiều bước riêng biệt. Mỗi bước tập trung vào một khía cạnh của đối tượng.
Các đại diện chỉ đơn giản lưu trữ kết quả, không cần quan tâm đến quá trình tạo ra chúng.
Đặt vấn đề
Trong phát triển phần mềm, ta thường gặp các đối tượng phức tạp với nhiều thuộc tính và thành phần. Ví dụ một đối tượng House có thể bao gồm các thành phần như phòng khách, phòng ngủ, nhà bếp, cửa ra vào, cửa sổ, hệ thống điện, nước, và nhiều thành phần khác.
Quá trình khởi tạo phức tạp, dễ gây nhầm lẫn với nhiều tham số truyền vào
Các thành phần của
House
bị phụ thuộc lẫn nhau, khó thay đổi một phần mà không ảnh hưởng các thành phần khác.Khó tạo các biến thể khác nhau của
House
một cách linh hoạt.
Như vậy, việc xây dựng các đối tượng phức tạp cần được thiết kế cẩn thận để tránh các vấn đề trên.
Giải quyết Vấn Đề
Builder Pattern giúp giải quyết vấn đề của việc tạo ra đối tượng phức tạp, như ví dụ sau về việc xây dựng một ngôi nhà. Thay vì tạo ngôi nhà một cách trực tiếp từng phần, chúng ta chia quá trình này thành nhiều bước riêng biệt. Mỗi bước tập trung vào việc xây dựng một khía cạnh cụ thể của ngôi nhà, chẳng hạn như cửa, cửa sổ và nhà bếp.
Cách hoạt động
Director (Quản lý): Đầu tiên, chúng ta có một người quản lý, được gọi là Director. Quản lý này có nhiệm vụ chỉ đạo quá trình xây dựng ngôi nhà.
Các Concrete Builder (Xây dựng cụ thể): Sau đó, chúng ta có các xây dựng cụ thể, ví dụ: Xây dựng Cửa, Xây dựng Cửa sổ và Xây dựng Nhà bếp. Mỗi Concrete Builder chịu trách nhiệm cho việc xây dựng một phần cụ thể của ngôi nhà.
Tạo ngôi nhà: Chúng ta kết hợp các phần đã xây dựng từ các Concrete Builder để tạo ra ngôi nhà hoàn chỉnh.
Ví dụ minh hoạ
Để hiểu rõ hơn, hãy xem ví dụ sau:
Director (Quản lý) gọi Concrete Builder (Xây dựng cụ thể) để bắt đầu xây dựng ngôi nhà.
Concrete Builder (Xây dựng cụ thể) thực hiện công việc của mình, ví dụ: xây dựng cửa, cửa sổ và nhà bếp.
Các phần này được kết hợp lại để tạo thành ngôi nhà hoàn chỉnh.
Kết quả là, người dùng ngôi nhà không cần quan tâm đến chi tiết cụ thể của quá trình xây dựng, mà chỉ cần sử dụng ngôi nhà đã hoàn thành một cách dễ dàng.
Cấu trúc
Builder Pattern có cấu trúc đơn giản, bao gồm các thành phần sau:
Builder: Định nghĩa phương thức xây dựng chung.
ConcreteBuilder: Triển khai chi tiết các bước xây dựng cụ thể.
Director: Sử dụng Builder để xây dựng sản phẩm.
Product: Là sản phẩm được tạo ra, chứa các phần do Builder tạo.
Như vậy Builder tách rời quá trình xây dựng phức tạp thành nhiều bước đơn giản, từng bước tập trung vào một khía cạnh riêng lẻ.
Cách triển khai
Builder Pattern có thể được triển khai theo nhiều cách khác nhau. Trong Java, có một số cách triển khai phổ biến như sau:
Định nghĩa Product: Chúng ta bắt đầu bằng việc định nghĩa lớp Product
để lưu trữ thông tin đối tượng cuối cùng:
Định nghĩa Builder: Sau đó, chúng ta định nghĩa lớp Builder
với các phương thức xây dựng, nhưng với Builder, mỗi phương thức xây dựng trả về chính builder, cho phép chúng ta gọi tiếp theo một cách liền mạch:
Bây giờ, chúng ta có thể sử dụng Builder để xây dựng sản phẩm một cách dễ đọc và gần gũi:
Giải thích
Chúng ta đã tạo một lớp
Builder
với các phương thức xây dựng trả về chính builder. Điều này cho phép chúng ta gọi tiếp các phương thức một cách liền mạch, tạo một chuỗi dễ đọc để xây dựng sản phẩm.Khi sử dụng Builder, các phương thức xây dựng có thể được gọi nối tiếp trên một đối tượng builder duy nhất, giúp giảm bớt sự phức tạp trong mã nguồn và làm cho mã trở nên rõ ràng hơn.
Cuối cùng, chúng ta gọi
getResult()
để lấy đối tượng Product đã được xây dựng và hiển thị nó.
Ví dụ minh họa
Dưới đây là một ví dụ minh họa về Builder Pattern trong Java:
Trong ví dụ này, chúng ta sử dụng phương pháp Builder để xây dựng một đối tượng House
, đại diện cho một ngôi nhà. Ví dụ này tách rời quá trình xây dựng ngôi nhà thành nhiều bước riêng biệt, và mỗi bước tập trung vào xây dựng một phần cụ thể của ngôi nhà.
Đối tượng Product: Nhà (House):
Trong ví dụ này,
House
là đối tượng mà chúng ta muốn xây dựng.House
có các thuộc tính nhưfoundation
,walls
,roof
, vàinterior
, đại diện cho các phần cấu trúc và nội thất của ngôi nhà.Chúng ta định nghĩa các phương thức
setPart
để thiết lập các phần của ngôi nhà vàshowHouseDetails
để hiển thị thông tin chi tiết của ngôi nhà.
Builder Interface: Builder:
HouseBuilder
là một giao diện định nghĩa các phương thức để xây dựng một đối tượngHouse
.Các phương thức trong
HouseBuilder
bao gồmbuildFoundation
,buildWalls
,buildRoof
, vàbuildInterior
, mỗi phương thức tương ứng với việc xây dựng một phần cụ thể của ngôi nhà.getResult
để lấy đối tượngHouse
đã hoàn thành.
Concrete Builder: ConcreteHouseBuilder:
ConcreteHouseBuilder
là lớp cụ thể triển khaiHouseBuilder
.Các phương thức của
ConcreteHouseBuilder
được triển khai để xây dựng các phần của ngôi nhà. Ví dụ,buildFoundation
thiết lập phần nền móng của ngôi nhà là "Concrete Foundation".Mỗi phương thức trả về chính đối tượng
ConcreteHouseBuilder
để cho phép chuỗi gọi phương thức (method chaining).
Director: HouseDirector:
HouseDirector
là lớp chịu trách nhiệm hướng dẫn quá trình xây dựng ngôi nhà.Nó chấp nhận một đối tượng
HouseBuilder
(ở đây làConcreteHouseBuilder
) thông qua hàm tạo và sẽ sử dụng nó để xây dựng ngôi nhà.constructHouse
phương thức củaHouseDirector
gọi các phương thức xây dựng trên builder để xây dựng các phần khác nhau của ngôi nhà theo đúng thứ tự.
Main class:
Trong hàm
main
, chúng ta bắt đầu bằng việc tạo một đối tượngConcreteHouseBuilder
.Sau đó, chúng ta tạo một đối tượng
HouseDirector
và kết nối nó vớiConcreteHouseBuilder
.Gọi
constructHouse
để bắt đầu quá trình xây dựng ngôi nhà.Cuối cùng, sử dụng
getResult
để nhận đối tượngHouse
đã hoàn thành và gọishowHouseDetails
để hiển thị thông tin chi tiết về ngôi nhà.
Kết quả là, chúng ta đã xây dựng một đối tượng ngôi nhà một cách dễ dàng và linh hoạt, trong đó mỗi phần của ngôi nhà được xây dựng bằng cách sử dụng Builder Pattern. Điều này giúp giảm sự phức tạp và làm cho mã nguồn trở nên rõ ràng hơn.
So sánh
Builder Pattern có thể được so sánh với một số Design Pattern tương tự, bao gồm:
Factory Pattern: Builder Pattern tập trung vào xây dựng một đối tượng phức tạp bằng cách tạo và cấu hình từng phần, trong khi Factory Pattern tập trung vào việc tạo đối tượng duy nhất và trả về nó.
Abstract Factory Pattern: Cả Builder Pattern và Abstract Factory Pattern đều giúp trong việc tạo đối tượng phức tạp, nhưng Abstract Factory tạo ra một tập hợp các đối tượng có liên quan và cung cấp một giao diện chung để tạo chúng, trong khi Builder tập trung vào việc xây dựng một đối tượng duy nhất.
Singleton Pattern: Singleton Pattern chỉ đảm bảo rằng một lớp chỉ có một đối tượng duy nhất và cung cấp một điểm truy cập đến nó. Builder Pattern không liên quan đến việc tạo đối tượng duy nhất mà tập trung vào việc xây dựng đối tượng phức tạp.
Kết luận
Builder Pattern là một Design Pattern hữu ích trong những trường hợp cần xây dựng các đối tượng phức tạp. Builder Pattern giúp việc xây dựng các đối tượng phức tạp trở nên dễ dàng hơn và ít xảy ra lỗi hơn.
Nên sử dụng Builder Pattern khi:
Đối tượng phức tạp có nhiều thuộc tính hoặc thành phần.
Cần xây dựng nhiều phiên bản khác nhau của đối tượng phức tạp.
Cần dễ dàng kiểm tra đối tượng phức tạp.
Không nên sử dụng Builder Pattern khi:
Đối tượng phức tạp không có nhiều thuộc tính hoặc thành phần.
Chỉ cần xây dựng một phiên bản duy nhất của đối tượng phức tạp.
Không cần dễ dàng kiểm tra đối tượng phức tạp.
Tôi hy vọng bài viết này đã giúp bạn hiểu rõ về Builder Pattern.