建造者模式將複雜物件的建構過程與其表示分離,使相同建構過程可建立不同表示。適用於建構步驟固定但內部結構複雜的物件。本文以購物車還原為例完整實作。
<?php
// 產品:購物車
class ShoppingCart {
private $goods = [];
private $tickets = [];
public function addGoods($goods) { $this->goods[] = $goods; }
public function addTicket($ticket) { $this->tickets[] = $ticket; }
public function printInfo() {
printf("商品:%s, 優惠券:%s\n", implode(',', $this->goods), implode(',', $this->tickets));
}
}
// 建造者介面
interface CartBuilderInterface {
public function buildGoods(array $goods);
public function buildTickets(array $tickets);
public function getCart(): ShoppingCart;
}
// 具體建造者
class CartBuilder implements CartBuilderInterface {
private $cart;
public function __construct(ShoppingCart $cart) {
$this->cart = $cart;
}
public function buildGoods(array $goods) {
foreach ($goods as $item) {
$this->cart->addGoods($item);
}
}
public function buildTickets(array $tickets) {
foreach ($tickets as $ticket) {
$this->cart->addTicket($ticket);
}
}
public function getCart(): ShoppingCart {
return $this->cart;
}
}
// 指導者(可選,封裝建構順序)
class CartDirector {
public function buildFromSession(CartBuilderInterface $builder, array $sessionData) {
if (isset($sessionData['goods'])) {
$builder->buildGoods($sessionData['goods']);
}
if (isset($sessionData['tickets'])) {
$builder->buildTickets($sessionData['tickets']);
}
}
}
// 客戶端使用
$sessionData = [
'goods' => ['衣服', '鞋子'],
'tickets' => ['折扣10元'],
];
// 不使用建造者:業務邏輯分散在客戶端
// $cart = new ShoppingCart();
// foreach ($sessionData['goods'] as $g) $cart->addGoods($g);
// foreach ($sessionData['tickets'] as $t) $cart->addTicket($t);
// 使用建造者:封裝組裝邏輯
$cart = new ShoppingCart();
$builder = new CartBuilder($cart);
$director = new CartDirector();
$director->buildFromSession($builder, $sessionData);
echo "建構完成:\n";
$cart->printInfo();
| 特性 | 工廠模式 | 建造者模式 |
|---|---|---|
| 關注點 | 建立「什麼」物件 | 「如何」一步步建構物件 |
| 建構過程 | 單步驟完成 | 多步驟、可控制順序 |
| 產品複雜度 | 較簡單 | 複雜、多組件組合 |
| 回傳時機 | 立即回傳 | 建構完成後回傳 |