## **抽象工廠模式**
抽象工廠模式(Abstact Factory)是一種常見的軟件設計模式。該模式為一個產品族提供了統一的創建接口。當需要這個產品族的某一系列的時候,可以為此系列的產品族創建一個具體的工廠類。
**一、意圖**
抽象工廠模式提供一個創建一系統相關或相互依賴對象的接口,而無需指定它們具體的類【GOF95】
**二、抽象工廠模式結構圖**

**三、抽象工廠模式中主要角色**
**抽象工廠(Abstract Factory)角色:**它聲明一個創建抽象產品對象的接口。通常以接口或抽象類實現,所有的具體工廠類必須實現這個接口或繼承這個類。
**具體工廠(Concrete Factory)角色:**實現創建產品對象的操作。客戶端直接調用這個角色創建產品的實例。這個角色包含有選擇合適的產品對象的邏輯。通常使用具體類實現。
**抽象產品(Abstract Product)角色:**聲明一類產品的接口。它是工廠方法模式所創建的對象的父類,或它們共同擁有的接口。
**具體產品(Concrete Product)角色:**實現抽象產品角色所定義的接口,定義一個將被相應的具體工廠創建的產品對象。其內部包含了應用程序的業務邏輯。
**四、抽象工廠模式的優缺點
**抽象工廠模式的**優點**:
1、分離了具體的類
2、使增加或替換產品族變得容易
3、有利于產品的一致性
抽象工廠模式的**缺點**: 難以支持新種類的產品。這是因為AbstractFactory接口確定了可以被創建的產品集合。支持新各類的產品就需要擴展訪工廠接口,從而導致AbstractFactory類及其所有子類的改變。
抽象工廠就是以一種傾斜的方式支持增加新的產品中,它為新產品族的增加提供了方便,而不能為新的產品等級結構的增加提供這樣的方便。
**五、抽象工廠模式適用場景
**以下情況應當使用抽象工廠模式:
1、一個系統不應當依賴于產品類實例如何被創建、組合和表達的細節,這對于所有形態的工廠模式都是重要的。
2、這個系統的產品有多于一個的產品族,而系統只消費其中某一族的產品。
3、 同屬于同一個產品族的產品是在一起使用的,這一約束必須在系統的設計中體現出來。
4、系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使用客戶端不依賴于實現
**六、抽象工廠模式與其它模式
**單例模式(singleton模式):具體工廠類可以設計成單例類,由于工廠通常有一個就可以,因此具體工廠子類一般都實現為一個Singleton。
工廠方法模式(factory method模式):抽象工廠創建產品的方法定義為工廠方法。
原型模式(prototype模式):如果有多個可能的產品系列,具體的工廠也可以使用原型模式,具體工廠使用產品系列中
每一個產品的原型進行實例化并且通過復制它的原型來創建新的產品。
**七、抽象工廠模式PHP示例**
~~~
<?php
/**
* 抽象產品A
*/
interface AbstractProductA {
/**
* 取得產品名
*/
public function getName();
}
/**
* 抽象產品B
*/
interface AbstractProductB {
/**
* 取得產品名
*/
public function getName();
}
/**
* 具體產品A1
*/
class ProductA1 implements AbstractProductA {
private $_name;
public function __construct() {
$this->_name = 'product A1';
}
public function getName() {
return $this->_name;
}
}
/**
* 具體產品A2
*/
class ProductA2 implements AbstractProductA {
private $_name;
public function __construct() {
$this->_name = 'product A2';
}
public function getName() {
return $this->_name;
}
}
/**
* 具體產品B1
*/
class ProductB1 implements AbstractProductB {
private $_name;
public function __construct() {
$this->_name = 'product B1';
}
public function getName() {
return $this->_name;
}
}
/**
* 具體產品B2
*/
class ProductB2 implements AbstractProductB {
private $_name;
public function __construct() {
$this->_name = 'product B2';
}
public function getName() {
return $this->_name;
}
}
/**
* 抽象工廠
*/
interface AbstractFactory {
/**
* 創建等級結構為A的產品的工廠方法
*/
public function createProductA();
/**
* 創建等級結構為B的產品的工廠方法
*/
public function createProductB();
}
/**
* 具體工廠1
*/
class ConcreteFactory1 implements AbstractFactory{
public function createProductA() {
return new ProductA1();
}
public function createProductB() {
return new ProductB1();
}
}
/**
* 具體工廠2
*/
class ConcreteFactory2 implements AbstractFactory{
public function createProductA() {
return new ProductA2();
}
public function createProductB() {
return new ProductB2();
}
}
/**
* 客戶端
*/
class Client {
/**
* Main program.
*/
public static function main() {
self::run(new ConcreteFactory1());
self::run(new ConcreteFactory2());
}
/**
* 調用工廠實例生成產品,輸出產品名
* @param $factory AbstractFactory 工廠實例
*/
public static function run(AbstractFactory $factory) {
$productA = $factory->createProductA();
$productB = $factory->createProductB();
echo $productA->getName(), '<br />';
echo $productB->getName(), '<br />';
}
}
Client::main();
?>
~~~
- PHP篇
- 函數傳值和傳引用的區別
- 簡述PHP的垃圾回收機制
- 簡述CGI、FAST-CGI、PHP-FPM的關系
- 常見正則表達式
- 多進程寫文件,如何保證都寫成功
- php支持回調函數的數組函數
- MySQL篇
- MySQL的兩種存儲引擎區別
- 事務的四大特性
- 數據庫事務隔離級別
- 什么是索引
- 索引有哪些數據結構,優缺點
- 索引的一些潛規則
- SQL的優化方案
- 簡述MySQL的鎖機制
- 死鎖是怎么產生的?怎么解決?
- 簡述MySQL的主從復制過程,延遲問題怎么解決
- 分布式事務的解決方案
- 數據庫中間件MyCat
- Linux篇
- Linux常用命令
- 對日志文件的IP出現的次數進行統計,并顯示次數最多的前5名
- WEB篇
- 跨域是怎么產生的,如何解決跨域
- Redis篇
- redis介紹
- redis和memcached區別
- redis的持久化方案
- 緩存穿透、擊穿、雪崩、預熱、更新、降級
- 網絡篇
- 計算機網絡體系結構
- 簡述TCP的三次握手、四次揮手過程
- UDP、TCP 區別,適用場景
- HTTP常見狀態碼含義
- 設計模式篇
- 單例模式
- 簡單工廠模式
- 抽象工廠模式
- 觀察者模式
- 策略模式
- 注冊模式
- 適配器模式
- 安全篇
- 跨站腳本攻擊(XSS)
- 跨站點請求偽造(CSRF)
- SQL 注入
- 應用層拒絕服務攻擊
- PHP安全
- 運維篇
- docker面試題
- 消息隊列篇
- 架構篇
- 數據結構與算法篇