Builder Pattern là gì?
Builder pattern là một trong những Creational pattern. Builder pattern là mẫu thiết kế đối tượng được tạo ra để xây dựng một đôi tượng phức tạp bằng cách sử dụng các đối tượng đơn giản và sử dụng tiếp cận từng bước, việc xây dựng các đối tượng đôc lập với các đối tượng khác.
Sử dụng Builder pattern sẽ tránh được các điều sau:
- Có quá nhiều tham số phải truyền vào hàm khởi tạo của classs.
- Một số tham số có thể là tùy chọn nhưng chúng ta phải gửi tất cả tham số, với tham số tùy chọn nếu ko nhập gì thì sẽ truyền là null.
Chúng ta có thể giải quyết các vấn đề nêu trên bằng cách cung cấp một hàm khởi tạo với những tham số bắt buộc và các phương thức getter/ setter để cài đặt các tham số tùy chọn. Tuy nhiên, hướng tiếp cận này sẽ khiến cho trạng thái của đối tượng trở nên không nhất quán cho tới khi tất cả các thuộc tính của nó được cài đặt một cách rõ ràng.
Xuất phát từ lý do đó, builder pattern đã được ra đời. Nó giải quyết vấn đề trên này bằng việc cung cấp một cách xây dựng đối tượng từng bước một và cung cấp một phương thức để trả về đối tượng cuối cùng.
Cấu trúc

Product : đại diện cho đối tượng cần tạo, đối tượng này phức tạp, có nhiều thuộc tính.
Builder : là abstract class hoặc interface khai báo phương thức tạo đối tượng.
ProductBuilder : kế thừa Builder và cài đặt chi tiết cách tạo ra đối tượng. Nó sẽ xác định và nắm giữ các thể hiện mà nó tạo ra, đồng thời nó cũng cung cấp phương thức để trả các các thể hiện mà nó đã tạo ra trước đó.
Director/ Client: là nơi sẽ gọi tới Builder để tạo ra đối tượng.
Code
Từ ví dụ trên ta sẽ xây dựng ProductBuilder như sau:
class Product
`
<?phpclass Product { protected $name; protected $sku; protected $slug; protected $content; protected $description; protected $price; protected $high_price; protected $inventory; protected $status;
public function __set($key, $value) { if (property_exists($this, $key)) { $this->$key = $value; } }
public function __get($key) { $retval = false; if (property_exists($this, $key)) { $retval = $this->$key; } else { $retval = false; }
return $retval; } }
`
Interface Builder
`
<?phpinterface Builder { public function reset (); public function buildName ($value); public function buildSku ($value); public function buildSlug ($value); public function buildDescription ($value); public function buildContent ($value); public function buildPrice ($value); public function buildHighPrice ($value); public function buildInventory ($value); public function buildStatus ($value); public function getResult(); }
`
class ProductBuilder
`
<?phpclass ProductBuilder implements Builder { private $product; public function __construct() { $this->product = new Product(); }
public function reset () { $this->product = new Product(); }
public function buildName ($value) { $this->product->name = $value; return $this; }
public function buildSku ($value) { $this->product->sku = $value; return $this; }
public function buildSlug ($value) { $this->product->slug = $value; return $this; }
public function buildDescription ($value) { $this->product->description = $value; return $this; }
public function buildContent ($value) { $this->product->content = $value; return $this; }
public function buildPrice ($value) { $this->product->price = $value; return $this; }
public function buildHighPrice ($value) { $this->product->high_price = $value; return $this; }
public function buildInventory ($value) { $this->product->inventory = $value; return $this; }
public function buildStatus ($value) { $this->product = $value; return $this; }
public function getResult() { return $this->product; } }
`
Sử dụng:
`
$productBuilder = new ProductBuilder();$product = $productBuilder ->buildName(”) ->buildSku(‘P001111’) ->buildDescription(‘Mô tả ngắn’) ->buildContent(‘Mô tả sản phẩm’) ->buildPrice(‘1000000’) ->getResult();
`
Lợi ích của Builder pattern
Hỗ trợ, loại bớt việc phải viết nhiều constructor.
Code dễ đọc, dễ bảo trì hơn khi số lượng thuộc tính (propery) bắt buộc để tạo một object từ 4 hoặc 5 propery.
Giảm bớt số lượng constructor, không cần truyền giá trị null cho các tham số không sử dụng.
Ít bị lỗi do việc gán sai tham số khi mà có nhiều tham số trong constructor: bởi vì người dùng đã biết được chính xác giá trị gì khi gọi phương thức tương ứng.
Đối tượng được xây dựng an toàn hơn: bởi vì nó đã được tạo hoàn chỉnh trước khi sử dụng.
Cung cấp cho bạn kiểm soát tốt hơn quá trình xây dựng: chúng ta có thể thêm xử lý kiểm tra ràng buộc trước khi đối tượng được trả về người dùng.
Có thể tạo đối tượng immutable.
Nên sử dụng Builder Pattern khi nào
Tạo một đối tượng phức tạp: có nhiều thuộc tính (nhiều hơn 4) và một số bắt buộc (requried), một số không bắt buộc (optional).
Khi có quá nhiều hàm constructor, bạn nên nghĩ đến Builder.
Muốn tách rời quá trình xây dựng một đối tượng phức tạp từ các phần tạo nên đối tượng.
Muốn kiểm soát quá trình xây dựng.
Khi người dùng (client) mong đợi nhiều cách khác nhau cho đối tượng được xây dựng.
Bạn không muốn việc gán giá trị cho các tham số của hàm khởi tạo phải tuân theo một trật tự cố định nào đó, ví dụ: Thay vì phải gán giá trị tuần tự từ tham số A rồi mới đến tham số B và tham số C, bạn có thể gán giá trị cho tham số B trước rồi mới đến A và C








(4 lượt thả tim)



