設計模式(二) 建造者模式
參考:http://www.runoob.com/design-pattern/builder-pattern.html
介紹
意圖:將一個複雜的構建與其表示相分離,使得同樣的構建過程可以建立不同的表示。
主要解決:主要解決在軟體系統中,有時候面臨著"一個複雜物件"的建立工作,其通常由各個部分的子物件用一定的演算法構成;由於需求的變化,這個複雜物件的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。
何時使用:一些基本部件不會變,而其組合經常變化的時候。
如何解決:將變與不變分離開。
關鍵程式碼:建造者:建立和提供例項,導演:管理建造出來的例項的依賴關係。
應用例項:
使用場景: 1、需要生成的物件具有複雜的內部結構。 2、需要生成的物件內部屬性本身相互依賴。
注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。
實現
我們假設一個快餐店的商業案例,其中,一個典型的套餐可以是一個漢堡(Burger)和一杯冷飲(Cold drink)。漢堡(Burger)可以是素食漢堡(Veg Burger)或雞肉漢堡(Chicken Burger),它們是包在紙盒中。冷飲(Cold drink)可以是可口可樂(coke)或百事可樂(pepsi),它們是裝在瓶子中。
我們將建立一個表示食物條目(比如漢堡和冷飲)的 Item 介面和實現 Item 介面的實體類,以及一個表示食物包裝的 Packing 介面和實現 Packing介面的實體類,漢堡是包在紙盒中,冷飲是裝在瓶子中。
然後我們建立一個 Meal 類,帶有 Item 的 ArrayList 和一個通過結合 Item 來建立不同型別的 Meal 物件的 MealBuilder。BuilderPatternDemo,我們的演示類使用 MealBuilder
以下用php程式碼示例:
<?php
interface Item{
public function name();
public function packing();
public function price();
}
interface Packing{
public function getPack();
}
class Wrapper implements Packing{
public function getPack(){
return 'wrapper';
}
}
class Bottle implements Packing{
public function getPack(){
return 'bottle';
}
}
abstract class Burger implements Item{
public function packing(){
return new Wrapper();
}
}
abstract class ColdDrink implements Item{
public function packing(){
return new Bottle();
}
}
class VegBurger extends Burger{
public function name(){
return 'VegBurger';
}
public function price(){
return 20;
}
}
class ChickenBurger extends Burger{
public function name(){
return 'ChickenBurger';
}
public function price(){
return 40;
}
}
class Pepsi extends ColdDrink{
public function name(){
return 'Pepsi';
}
public function price(){
return 10;
}
}
class Coke extends ColdDrink{
public function name(){
return 'Coke';
}
public function price(){
return 11;
}
}
class Meal{
public $item;
public $price=0;
public $mealList = '';
public function add(Item $item){
$this->item[] = $item;
}
public function getOrder(){
foreach($this->item as $item){
$this->mealList .= "名稱:".$item->name()."\n";
$this->mealList .= "價格:".$item->price()."\n";
$this->mealList .= "包裝:".$item->packing()->getPack()."\n\n";
$this->price += $item->price();
}
$this->mealList .= "\n總計:" . $this->price ."\n\n";
print_r($this->mealList);
}
}
class MealBuilder extends Meal{
public function a1(){
$this->add(new VegBurger());
$this->add(new Pepsi());
}
public function a2(){
$this->add(new ChickenBurger());
$this->add(new Pepsi());
}
public function b1(){
$this->add(new ChickenBurger());
$this->add(new Coke());
}
public function b2(){
$this->add(new ChickenBurger());
$this->add(new Coke());
}
public function free($arr)
{
foreach($arr as $item){
$this->add($item);
}
}
}
$mealBuilder = new MealBuilder();
$mealBuilder->a1();
$mealBuilder->getOrder();
$mealBuilder2 = new MealBuilder();
$mealBuilder2->free([new VegBurger(),new ChickenBurger(),new Pepsi()]);
$mealBuilder2->getOrder();
上面的例子比較靈活,但不是太側重“同樣的構建過程”。比較常見的是下面這種只有一個產品的模式結構,大多數的書中也是這樣講的。
參考:https://blog.csdn.net/xingjiarong/article/details/50037099
在實際的應用中不可能只用建立者模式建立一種產品如。
以汽車構建為例:
<?php
interface engine{
public function getEngine();
}
interface wheel{
public function getWheel();
}
interface body{
public function getBody();
}
class AudiEngine implements engine{
public function getEngine(){
return '奧迪引擎';
}
}
class BaomaEngine implements engine{
public function getEngine(){
return '寶馬引擎';
}
}
class AudiWheel implements wheel{
public function getWheel(){
return '奧迪車輪';
}
}
class BaomaWheel implements wheel{
public function getWheel(){
return '寶馬車輪';
}
}
class AudiBody implements body{
public function getBody(){
return '奧迪車身';
}
}
class BaomaBody implements body{
public function getBody(){
return '寶馬車身';
}
}
class CarProduct{
public $engine;
public $wheel;
public $body;
}
abstract class CarBuilder{
protected $car;
public function __construct(){
$this->car = new CarProduct();
}
public abstract function buildEngine();
public abstract function buildWheel();
public abstract function buildBody();
public function getCar(){
return $this->car;
}
}
class AudiBuilder extends CarBuilder{
public function buildEngine(){
$this->car->engine = new AudiEngine();
}
public function buildWheel(){
$this->car->wheel = new AudiWheel();
}
public function buildBody(){
$this->car->body = new AudiBody();
}
}
class BaomaBuilder extends CarBuilder{
public function buildEngine(){
$this->car->engine = new BaomaEngine();
}
public function buildWheel(){
$this->car->wheel = new BaomaWheel();
}
public function buildBody(){
$this->car->body = new BaomaBody();
}
}
class director{
public function createCar(CarBuilder $car){
//通常的做法是buildEngine($car),在buildEngine根據不同的car引數做不同的處理
//如此會把所有的業務邏輯都壓在createCar模組。
//使用構造方法,可解耦此邏輯,各自car的buildEngine各自處理
$car->buildEngine();
$car->buildWheel();
$car->buildBody();
return $car;
}
}
$carBuilder = new AudiBuilder();
// $carBuilder = new BaomaBuilder();
$director = new director();
$car = $director->createCar($carBuilder);
var_dump($car->getCar()->engine->getEngine());
var_dump($car->getCar()->wheel->getWheel());
var_dump($car->getCar()->body->getBody());