1. 程式人生 > >設計模式(二) 建造者模式

設計模式(二) 建造者模式

參考:http://www.runoob.com/design-pattern/builder-pattern.html

介紹

意圖:將一個複雜的構建與其表示相分離,使得同樣的構建過程可以建立不同的表示。

主要解決:主要解決在軟體系統中,有時候面臨著"一個複雜物件"的建立工作,其通常由各個部分的子物件用一定的演算法構成;由於需求的變化,這個複雜物件的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。

何時使用:一些基本部件不會變,而其組合經常變化的時候。

如何解決:將變與不變分離開。

關鍵程式碼:建造者:建立和提供例項,導演:管理建造出來的例項的依賴關係。

應用例項:

 1、去肯德基,漢堡、可樂、薯條、炸雞翅等是不變的,而其組合是經常變化的,生成出所謂的"套餐"

使用場景: 1、需要生成的物件具有複雜的內部結構。 2、需要生成的物件內部屬性本身相互依賴。

注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。

實現

我們假設一個快餐店的商業案例,其中,一個典型的套餐可以是一個漢堡(Burger)和一杯冷飲(Cold drink)。漢堡(Burger)可以是素食漢堡(Veg Burger)或雞肉漢堡(Chicken Burger),它們是包在紙盒中。冷飲(Cold drink)可以是可口可樂(coke)或百事可樂(pepsi),它們是裝在瓶子中。

我們將建立一個表示食物條目(比如漢堡和冷飲)的 Item 介面和實現 Item 介面的實體類,以及一個表示食物包裝的 Packing 介面和實現 Packing介面的實體類,漢堡是包在紙盒中,冷飲是裝在瓶子中。

然後我們建立一個 Meal 類,帶有 Item 的 ArrayList 和一個通過結合 Item 來建立不同型別的 Meal 物件的 MealBuilderBuilderPatternDemo,我們的演示類使用 MealBuilder

 來建立一個 Meal

以下用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());