1. 程式人生 > >設計模式 一 工廠方法Factory Method(工廠模式)

設計模式 一 工廠方法Factory Method(工廠模式)

<?php
/**
 * 工廠方法模式演變
 *
 * 比薩加盟店
 * 背景:隨著比薩店的發展,有更多人想成為比薩加盟店。
 */


/**
 * 每家加盟店都可能想要提供不同風味的比薩(比方說紐約、芝加哥、加州),這受到了開店地點影響。
 */


/**
 * 我們已經有一個做法。。。
 * 如果利用SimpleFactory,寫出三種不同的工廠,分別為NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory,那麼各地加盟店都有適合的工廠可以使用,這是一種做法。
 */

$NYPizzaFactory = new NYPizzaFactory();
$nyStore = new PizzaStore($NYPizzaFactory);
$nyStore->orderPizza("veggie");


$ChicagoPizzaFactory = new NYPizzaFactory();
$chicagoStore = new PizzaStore($ChicagoPizzaFactory);
$chicagoStore->orderPizza("veggie");


/**
 * 但是你想要多一些質量控制。。。。
 * 在推廣SimpleFactory時,你發現加盟店的確是採用你的工廠建立比薩,但其他部分,卻開始採用他們自創的流程。
 * 烘烤的做法有些差異、不要切片、使用其他廠商的盒子。
 */


/**
 * 讓子類決定,給比薩店使用框架。
 * 有個做法可以讓比薩製作活動侷限於pizzaStore類,而同時又能讓這些加盟店依然可以自由製作該區域的風味。
 * 所有做的事情,就是把 createPizza() 設定為“抽象方法”,然後為每個區域風味建立一個PizzaStore 的子類。
 * 抽象、介面實現多型。
 */

 abstract class PizzaStore {
	//public $factory;
	//public function __construct(SimpleFactory $simpleFactory ) {
	//	$this->factory = $simpleFactory;
	//}
	
	public function orderPizza($type) {		
		//為了讓系統有彈性,我們很希望這是一個抽象類或介面。
		//$pizza = $this->factory->createPizza($type); //變化部分
		$pizza = $this->createPizza($type);

		$pizza->prepare(); //準備
		$pizza->bake(); //烘烤
		$pizza->cut(); //切片
		$pizza->box(); //包裝
		return $pizza;
	}

	abstract public function createPizza($type);
}

/**
 * 現在已經有了PizzaStore 超類,讓 NYPizzaStore,ChicagoPizzaStore等 都繼承這個PizzaStore,由子類決定如何製作比薩。
 *
 */

/**
 * 子類如何做決定
 * 關於這個方面,需要從PizzaStore的orderPizza()方法觀點來看,更進一步地,orderPizza()方法對pizza做了許多事情(準備、烘烤、切片、包裝)
 * 但由於Pizza物件是抽象的,orderPizza()並不知道哪些實際的具體類參與了進來,這不是orderPizza()方法決定的,換句話,這就是解耦。
 * 那麼,子類是實時作出這樣的決定嗎?不是,但從orderPizza()的角度來看,如果選擇在NYStylePizzaStore訂購比薩,就是由這個子類(NYStylePizzaStore)決定。
 * 嚴格來說,並非由這個子類實際做“決定”,而是由“顧客”決定到哪一家風味比薩店才決定了比薩風味。
 */

class NYPizzaStore extends PizzaStore {
	public function createPizza($type) {
		if ("cheese" == $type) {//乳酪比薩
			$pizza = new NYStyleCheesePizza(); 		
		} elseif ("greek" == $type) {//希臘比薩
			$pizza = new NYStyleGreekPizza();		
		} elseif ("pepperoni" == $type) {//香腸比薩
			$pizza = new NYStylePepperoniPizza();		
		} else {
			return null;
		}
		return $pizza;
	}
}

$NYPizzaStore = new NYPizzaStore();
$pizza = $NYPizzaStore->orderPizza('cheese');

/**
 * 注意 orderPizza 已經實現了createPizza
 */




 /**
  * 總結 
  * 工廠方法模式 定義了一個建立物件的介面,但由子類決定要例項化的類時哪一個。工廠方法讓類把例項化推遲到子類。
  * 問:簡單工廠與工廠方法的差異
  * 答:工廠方法是用繼承擴充套件了一個類,而簡單工廠,工廠是另一個pizzastore使用物件。
  * 子類的確看起來像簡單工廠。簡單工廠把全部的事情,在一個地方處理完了。然而工廠方法卻是建立一個框架,讓子類決定要如何實現。
  * 比方說,在工廠方法中,orderPizza()方法提供了一般框架,以便建立比薩。orderPizza()依賴工廠方法建立具體類,並製造出實際的比薩。
  */


參考資料 :Head First 設計模式