Giới thiệu Builder pattern
Trong thực tế, đôi khi chúng ta cần tạo object phức tạp chứa nhiều data member. Các data member này có thể là các kiểu dữ liệu cơ bản hoặc là các object khác. Giá trị của chúng được truyền vào thông qua tham số hoặc sử dụng các hàm set. Một số trường hợp chúng ta có thể khởi tạo giá trị data member theo các bước, có trường hợp một số data member không cần dùng. Đối với class như này thì hàm khởi tạo như vậy sẽ có rất nhiều tham số hoặc gán giá trị cho data member sẽ nằm rải rác ở nhiều nơi. Điều này làm cho việc phát triển và bảo trì trở nên phức tạp hơn.
Để xử lý vấn đề trên, người ta xử dụng Builder pattern. Ý tưởng của Builder pattern như sau: Tách các biểu diễn trong việc xây dựng object phức tạp, để các biểu diễn này trong cùng một quá trình xây dựng object có thể tạo được nhiều kiểu object có kiểu khác nhau. Các biểu diễn ở đây là các bước để xây dựng object là giống nhau, từ đây ta có thể tạo ra các object khác nhau trong cùng 1 đoạn code xây dựng. Builder pattern được sử dụng xây dựng object phức tạp qua nhiều bước và kết quả cuối cùng sẽ trả về object cần tạo.
Dưới đây là một ví dụ cụ thể về Builder pattern:
Ví dụ về việc xây dựng nhà, 1 ngôi nhà đơn giản (House )gồm xây tường, lát nền nhà, lắp cửa sổ, cửa đi , lợp mái nhà. Thực tế thì có nhiều ngôi nhà phức tạp hơn như nhà có vườn, nhà có bể bơi, nhà có ga ra … Trong lập trình thì việc xây nhà này sẽ có cách giải quyết đơn giản việc này là House là base class còn các loại nhà phức tạp sẽ là các subclass của House với nhiều tham số như có bể hay không, có vườn …
Builder pattern sẽ tách code khởi tạo đối tượng và di chuyển nó sang lớp Builder.
Lớp Builder này sẽ tổ chức khởi tạo giá trị data member qua các bước. Lớp Builder này sẽ không gọi tất cả các bước để khởi tạo giá mà nó chỉ cần gọi các bước cần thiết. Với ví dụ trên ta có các bước như là build wall, build door, build windows … Một số bước có thể yêu cầu khác nhau thì cần cài đặt cụ thể ở 1 subclass của Builder. Ví dụ, bước xây tường thì ta có thể xây với gạch hoặc xây với đá.
Về cơ bản thì cấu trúc của Builder pattern có 4 phần như sau:
- Product: Đây là kiểu đối tượng phức tạp mà chúng ta cần xây dựng. Nó được tạo bởi class ConcreateBuilder
- Builder: Là interface hoặc abstract class. Nó chứa các bước (method) để xây dựng và trả về đối tượng phức tạp.
- ConcreateBuilder: Là các class implement của Builder. Nó cụ thể hoá các bước tạo đối tượng. Có thể có nhiều lớp Concreate Builder, số lượng Concreate Builder phụ thuộc vào số lượng Product cần tạo.
- Director: Là class chứa Builder, trong class này sẽ gọi các method ở ConcreateBuilder để trả về đối tượng phức tạp cần tạo.
Để dễ dàng cho việc triển khai Builder pattern vào trong thực tế thì trước khi sử dụng ta phải đi xác định cấu trúc của Builder trong bài toán của mình. Việc xác định này thông qua các câu hỏi sau:
- Các bước chung trong quá trình xây dựng object là gì ?
- Trong Interface Builder nên chứa các method nào ?
- Class ConcreateBuilder sẽ implement các method như nào ? Cần bao nhiêu class Product và ConcreateBuilder tương ứng
- Class Director sẽ tạo đối tượng Product như thế nào ? Thứ tự các bước xây dựng Product?