抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產品的具體的情況下,創建多個產品族中的產品對象。根據里氏替換原則,任何接受父類型的地方,都應當能夠接受子類型。因此,實際上系統所需要的,僅僅是類型與這些抽象產品角色相同的一些實例,而不是這些抽象產品的實例。換言之,也就是這些抽象產品的具體子類的實例。工廠類負責創建抽象產品的具體子類的實例。
基本介紹
- 中文名:抽象工廠模式
- 外文名:Abstract Factory
- 是指:當有多個抽象角色
- 根據:LSP原則
- 創建:多個產品族中的產品對象
定義
簡介
產品族
使用情況
使用
- 客戶端代碼不知道任何具體類型,也就沒必要引入任何相關的頭檔案或類定義。客戶端代碼僅僅處理抽象類型。工廠確實創建了具體類型的對象,但是客戶端代碼僅使用這些對象的抽象接口來訪問它們。
- 如果要增加一個具體類型,只需要修改客戶端代碼使用另一個工廠即可,而且這個修改通常只是一個檔案中的一行代碼。不同的工廠創建不同的具體類型的對象,但是和以前一樣返回一個抽象類型的引用(或指針),因此客戶端代碼的其他部分不需要任何改動。這樣比修改客戶端代碼創建新類型的對象簡單多了。如果是後者的話,需要修改代碼中每一個創建這種對象的地方(而且需要注意的是,這些地方都知道對象的具體類型,而且需要引入具體類型的頭檔案或類定義)。如果所有的工廠對象都存儲在全局的單例對象中,所有的客戶端代碼到這個單例中訪問需要的工廠,那么,更換工廠就非常簡單了,僅僅需要更改這個單例對象即可。
代碼舉例
C++
class Button; // Abstract Classclass MacButton: public Button {};class WinButton: public Button {};class Border; // Abstract Classclass MacBorder: public Border {};class WinBorder: public Border {};
class AbstractFactory {public: virtual Button* CreateButton() =0; virtual Border* CreateBorder() =0;};class MacFactory: public AbstractFactory {public: MacButton* CreateButton() { return new MacButton; } MacBorder* CreateBorder() { return new MacBorder; }};class WinFactory: public AbstractFactory {public: WinButton* CreateButton() { return new WinButton; } WinBorder* CreateBorder() { return new WinBorder; }};
AbstractFactory* fac;switch (style) {case MAC: fac = new MacFactory; break;case WIN: fac = new WinFactory; break;}Button* button = fac->CreateButton();Border* border = fac->CreateBorder();
PHP
<?php/*************************************************************************** * AbstractFactory.php * ------------------- * Time : 2006-11-11 * Coder : rollenc(http://www.rollenc.com) * syre(http://syre.blogbus.com) ***************************************************************************/abstract class AbstractFactory { abstract public function CreateButton(); abstract public function CreateBorder();}class MacFactory extends AbstractFactory{ public function CreateButton() { return new MacButton(); } public function CreateBorder() { return new MacBorder(); }}class WinFactory extends AbstractFactory{ public function CreateButton() { return new WinButton(); } public function CreateBorder() { return new WinBorder(); }}class Button{}class Border{}class MacButton extends Button{ function __construct() { echo 'MacButton is created' . "\n"; }}class MacBorder extends Border{ function __construct() { echo 'MacBorder is created' . "\n"; }}class WinButton extends Button{ function __construct() { echo 'WinButton is created' . "\n"; }}class WinBorder extends Border{ function __construct() { echo 'WinBorder is created' . "\n"; }}?>
<?$type = 'Mac'; //value by user. if(!in_array($type, array('Win','Mac'))) die('Type Error'); $factoryClass = $type.'Factory'; $factory=new $factoryClass; $factory->CreateButton(); $factory->CreateBorder();
Java
- 使用上面的例子
public interface Button {}public interface Border {}
- 實現抽象類
public class MacButton implements Button {}public class MacBorder implements Border {}public class WinButton implements Button {}public class WinBorder implements Border {}
- 接著實現工廠
public class MacFactory { public static Button createButton() { return new MacButton(); } public static Border createBorder() { return new MacBorder(); }}public class WinFactory { public static Button createButton() { return new WinButton(); } public static Border createBorder() { return new WinBorder(); }}
適用性
- 一個系統要獨立於它的產品的創建、組合和表示時。
- 一個系統要由多個產品系列中的一個來配置時。
- 需要強調一系列相關的產品對象的設計以便進行聯合使用時。
- 提供一個產品類庫,而只想顯示它們的接口而不是實現時。
優點
- 具體產品從客戶代碼中被分離出來
- 容易改變產品的系列
- 將一個系列的產品族統一到一起創建
缺點
- 在產品族中擴展新的產品是很困難的,它需要修改抽象工廠的接口