一、簡介
抽象工廠模式(Abstract Factory Pattern):提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬于對象創(chuàng)建型模式。
注意:這里和工廠方法的區(qū)別是:一系列(多個(gè)),而工廠方法只有一個(gè)。
二、類結(jié)構(gòu)
抽象工廠模式結(jié)構(gòu)如下:
| 角色 | 類別 | 簡述 |
|---|---|---|
| AbstractFactory | 抽象工廠 | 一般是一個(gè)抽象類或是接口 |
| ConcreteFactory | 具體工廠 | 用來創(chuàng)建一系列具體的產(chǎn)品 |
| AbstractProduct | 抽象產(chǎn)品 | 一個(gè)抽象類或是接口 |
| Product | 具體產(chǎn)品 | 用來創(chuàng)建具體的產(chǎn)品 |
三、UML圖
比如,我們需要設(shè)計(jì)一個(gè)繪圖工具:

四、代碼分析
1、抽象產(chǎn)品
圖形類接口:
interface Shape{
public function draw();
}
顏色類接口:
interface Color {
public function fill();
}
2、具體產(chǎn)品
具體圖形類:
//矩形類
class Rectangle implements Shape {
public function draw() {
echo '插入一個(gè)矩形 \n\r';
}
}
//正方形類
class Square implements Shape {
public function draw() {
echo '插入一個(gè)正方形 \n\r';
}
}
//圓形類
class Circle implements Shape {
public function draw() {
echo '插入一個(gè)圓形 \n\r';
}
}
具體顏色類:
//紅色類
class Red implements Color {
public function fill() {
echo '填充紅色 \n\r';
}
}
//綠色類
class Green implements Color {
public function fill() {
echo '填充綠色 \n\r';
}
}
//藍(lán)色類
class Blue implements Color {
public function fill() {
echo '填充藍(lán)色 \n\r';
}
}
3、抽象工廠
為 Color 和 Shape 對象創(chuàng)建抽象類來獲取工廠。
class interface AbstractFactory {
public function getColor($color);
public function getShape($shape) ;
}
4、具體工廠
//形狀工廠類
class ShapeFactory extends AbstractFactory {
public function getShape($shapeType){
if($shapeType == false){
return false;
}
if($shapeType=="circle"){
return new Circle();
} else if($shapeType=="rectangle"){
return new Rectangle();
} else if($shapeType=="square"){
return new Square();
}
return false;
}
public function getColor($color) {
return false;
}
}
//顏色工廠類
class ColorFactory extends AbstractFactory {
public function getShape($shapeType){
return false;
}
public function getColor($color) {
if($color == false){
return false;
}
if($color=="red"){
return new Red();
} else if($color=="green"){
return new Green();
} else if($color=="blue"){
return new Blue();
}
return false;
}
}
5、工廠創(chuàng)造器
創(chuàng)建一個(gè)工廠創(chuàng)造器/生成器類,通過傳遞形狀或顏色信息來獲取工廠。
class FactoryProducer {
public static function getFactory($choice){
if($choice=="shape")){
return new ShapeFactory();
} else if($choice=="color"){
return new ColorFactory();
}
return null;
}
}
6、使用實(shí)例
public class Demo {
public static function test() {
//獲取形狀工廠
$shapeFactory = FactoryProducer::getFactory("SHAPE");
//為形狀插入Circle對象
$shape1 = $shapeFactory->getShape("circle");
//調(diào)用 Circle 的 draw 方法
$shape1->draw();
//為形狀插入Rectangle對象
$shape2 = $shapeFactory->getShape("rectangle");
//調(diào)用 Rectangle 的 draw 方法
$shape2->draw();
//獲取顏色工廠
$colorFactory = FactoryProducer::getFactory("color");
//獲取顏色為 Red 的對象
$color1 = $colorFactory->getColor("red");
//調(diào)用 Red 的 fill 方法
$color1->fill();
}
}
Demo::test();
測試結(jié)果:
插入一個(gè)圓形
插入一個(gè)矩形
填充紅色
五、特點(diǎn)
1、優(yōu)點(diǎn)
- 抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創(chuàng)建。由于這種隔離,更換一個(gè)具體工廠就變得相對容易。所有的具體工廠都實(shí)現(xiàn)了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實(shí)例,就可以在某種程度上改變整個(gè)軟件系統(tǒng)的行為。另外,應(yīng)用抽象工廠模式可以實(shí)現(xiàn)高內(nèi)聚低耦合的設(shè)計(jì)目的,因此抽象工廠模式得到了廣泛的應(yīng)用。
- 當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對象被設(shè)計(jì)成一起工作時(shí),它能夠保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對象。這對一些需要根據(jù)當(dāng)前環(huán)境來決定其行為的軟件系統(tǒng)來說,是一種非常實(shí)用的設(shè)計(jì)模式。
- 增加新的具體工廠和產(chǎn)品族很方便,無須修改已有系統(tǒng),符合“開閉原則”。
2、缺點(diǎn)
- 在添加新的產(chǎn)品對象時(shí),難以擴(kuò)展抽象工廠來生產(chǎn)新種類的產(chǎn)品,這是因?yàn)樵诔橄蠊S角色中規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合,要支持新種類的產(chǎn)品就意味著要對該接口進(jìn)行擴(kuò)展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會(huì)帶來較大的不便。
- 開閉原則的傾斜性(增加新的工廠和產(chǎn)品族容易,增加新的產(chǎn)品等級結(jié)構(gòu)麻煩)。。
3、適用場景
在以下情況下可以考慮使用抽象工廠模式:
- 一個(gè)系統(tǒng)不應(yīng)當(dāng)依賴于產(chǎn)品類實(shí)例如何被創(chuàng)建、組合和表達(dá)的細(xì)節(jié),這對于所有類型的工廠模式都是重要的。
- 系統(tǒng)中有多于一個(gè)的產(chǎn)品族,而每次只使用其中某一產(chǎn)品族。
- 屬于同一個(gè)產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設(shè)計(jì)中體現(xiàn)出來。
- 系統(tǒng)提供一個(gè)產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于具體實(shí)現(xiàn)。