## 模式定義:
? ? ? 工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到子類。
## 模式結構:

? ? ? Creator是一個類,它實現了所有操縱產品的方法,但不實現工廠方法。Creator的所有子類都必須實現工廠方法(factoryMethod()),以實際制造出產品。
? ? ? 所有的產品必須實現Product基類,這樣一來使用這些產品的類就可以引用這個基類,而不是派生類。
## 舉例:
? ? ? 披薩店希望能夠開一些加盟店。經營者希望確保加盟店運營的質量,所以希望這些店都使用能經過實踐考研的代碼。問題在于每家加盟店都可能想要提供不同風味的披薩(比方說紐約,芝加哥,加州),這收到了開店地點及該地區披薩口味的影響。
? ? ? 解決辦法:讓每個區域風味的披薩工廠繼承基類披薩工廠使披薩工廠的訂單系統不變,然后創建自己風味的披薩。這樣真正選購披薩類型,使用具體的披薩工廠決定的。
## 類圖設計:

## 編程實現及執行結果:
~~~
#include <iostream>
#include <string>
#include <list>
using namespace std;
~~~
首先創建Pizza類
~~~
class Pizza
{
public:
Pizza(string nam, string doug, string sauc)
{
name = nam;
dough = doug;
sauce = sauc;
}
void addTops(string tops)
{
toppings.push_back(tops);
}
void prepare()
{
cout << "Preparing " << name << endl;
cout << "Tossing dough" << endl;
cout << "Adding sauce" << endl;
cout << "Adding toppings" << endl;
list<string>::iterator iter = toppings.begin();
for(; iter!=toppings.end(); ++iter)
{
cout << " "<< *iter;
}
cout << endl;
}
void bake()
{
cout << "Bake for 25 minutes at 350" << endl;
}
void cut()
{
cout << "Cutting the pizza into diagonal slices" << endl;
}
void box()
{
cout << "Place pizza in offical PizzaStore box" << endl;
}
string getName()
{
return name;
}
private:
string name;
string dough;
string sauce;
list<string> toppings;
};
~~~
然后創建紐約cheese風格的pizza類和紐約clam風格的pizza類
~~~
class NYStyleCheesePizza : public Pizza
{
public:
NYStyleCheesePizza():Pizza("NY Style Sauce and Cheese Pizza",
"Thin Crust Dough", "Marinara Sauce")
{
addTops("Grated Reggiano Cheese");
}
};
class NYStyleClamPizza : public Pizza
{
public:
NYStyleClamPizza():Pizza("NY Style Sauce and Clam Pizza",
"Thin Crust Dough", "Marinara Sauce")
{
addTops("Grated Clam");
}
};
~~~
創建基類工廠
~~~
class PizzaStore
{
public:
virtual ~PizzaStore(){}
Pizza* oderPizza(string type)
{
Pizza* pizza = createPizza(type);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
virtual Pizza* createPizza(string type){return NULL;}
};
~~~
創建具體類工廠(紐約pizza工廠)
~~~
class NYPizzaStore : public PizzaStore
{
public:
Pizza* createPizza(string item)
{
if(item == "cheese")
{
return new NYStyleCheesePizza();
}
else if(item == "clam")
{
return new NYStyleClamPizza();
}
else
return NULL;
}
};
//...創建其他地區工廠...
~~~
客戶代碼:
~~~
int main()
{
PizzaStore* nyStore = new NYPizzaStore();
Pizza* pizza = nyStore->oderPizza("cheese");
cout << "Ethan ordered a "<< pizza->getName() << endl;
return 0;
}
~~~
執行結果:
**PreparingNY Style Sauce and Cheese Pizza**
**Tossingdough**
**Addingsauce**
**Addingtoppings**
**Grated Reggiano Cheese**
**Bakefor 25 minutes at 350**
**Cuttingthe pizza into diagonal slices**
**Placepizza in offical PizzaStore box**
**Ethanordered a NY Style Sauce and Cheese Pizza**
**請按任意鍵繼續. . .**
## 設計原則的應用:
設計原則6:依賴倒置原則(Dependency Inversion Priciple):要依賴抽象,不要依賴具體類。
設計原則4:工廠方法用來處理對象的創建,并將這樣的行為封裝在子類中。這樣,客戶中關于基類的代碼和子類對象對象創建代碼解耦了。
參考Head First設計模式