PHP實現設計模式中的抽象原廠模式詳解,設計模式詳解_PHP教程

來源:互聯網
上載者:User

PHP實現設計模式中的抽象原廠模式詳解,設計模式詳解


抽象原廠模式(Abstact Factory)是一種常見的軟體設計模式。該模式為一個產品族提供了統一的建立介面。當需要這個產品族的某一系列的時候,可以為此系列的產品族建立一個 具體的工廠類。

【意圖】

抽象原廠模式提供一個建立一系統相關或相互依賴對象的介面,而無需指定它們具體的類【GOF95】

【抽象原廠模式結構圖】

【抽象原廠模式中主要角色】

抽象工廠(Abstract Factory)角色:它聲明一個建立抽象產品對象的介面。通常以介面或抽象類別實現,所有的具體工廠類必須實現這個介面或繼承這個類。

具體工廠(Concrete Factory)角色:實現建立產品對象的操作。用戶端直接調用這個角色建立產品的執行個體。這個角色包含有選擇合適的產品對象的邏輯。通常使用具體類實現。

抽象產品(Abstract Product)角色:聲明一類產品的介面。它是Factory 方法模式所建立的對象的父類,或它們共同擁有的介面。

具體產品(Concrete Product)角色:實現抽象產品角色所定義的介面,定義一個將被相應的具體工廠建立的產品對象。其內部包含了應用程式的商務邏輯。

【抽象原廠模式的優缺點】

抽象原廠模式的優點:
1、分離了具體的類
2、使增加或替換產品族變得容易
3、有利於產品的一致性

抽象原廠模式的缺點: 難以支援新種類的產品。這是因為AbstractFactory介面確定了可以被建立的產品集合。支援新各類的產品就需要擴充訪工廠介面,從而導致 AbstractFactory類及其所有子類的改變。
抽象工廠就是以一種傾斜的方式支援增加新的產品中,它為新產品族的增加提供了方便,而不能為新的產品等級結構的增加提供這樣的方便。

【抽象原廠模式適用情境】

以下情況應當使用抽象原廠模式:
1、一個系統不應當依賴於產品類執行個體如何被建立、組合和表達的細節,這對於所有形態的原廠模式都是重要的。
2、這個系統的產品有多於一個的產品族,而系統只消費其中某一族的產品。
3、 同屬於同一個產品族的產品是在一起使用的,這一約束必須在系統的設計中體現出來。
4、系統提供一個產品類的庫,所有的產品以同樣的介面出現,從而使用用戶端不依賴於實現
【Java與模式189頁】

Abstract Factory模式的幾個要點:

1、如果沒有應對“多系列對象構建”的需求變化,則沒有必要使用Abstract Factory模式。
2、“系列對象”指的是這項對象之間有相互依賴、或作用的關係。
3、Abstract Factory模式主要在於應對“新系列”的需求變動。缺點是難以應對
“新對象”的需求變動。這一點應該注意,就像前面說的,如果我們現在要在加入
其他系列的類,代碼的改動會很大。
4、Abstract Factory模式經常和Factory Method模式共同組合來應對
“對象建立”的需求變化。

抽象工廠中的增加

1. 在產品等級結構的數目不變的情況下,增加新的產品族,就意味著在每一個產品等級結構中增加一個(或者多個)新的具體 (或者抽象和具體)產品角色。 由於工廠等級結構是與產品等級結構平行的登記機構,因此,當產品等級結構有所調整時, 需要將工廠等級結構做相應的調整。現在產品等級結構中出現了新的元素,因此, 需要向工廠等級結構中加入相應的新元素就可以了。 換言之,設計師只需要向系統中加入新的具體工廠類就可以了,沒有必要修改已 有的工廠角色或者產品角色。因此,在系統中的產品族增加時,抽象原廠模式是支援“開-閉”原則的。

2. 在產品族的數目不變的情況下,增加新的產品等級結構。換言之,所有的產品等級結構 中的產品數目不會改變,但是現在多出一個與現有的產品等級結構平行的新的產品等級結構。 要做到這一點,就需要修改所有的工廠角色,給每一個工廠類都增加一個新的Factory 方法, 而這顯然是違背“開–閉”原則的。換言之,對於產品等級結構的增加,抽象原廠模式是不支援“開–閉”原則的。

綜合起來,我們可以知道,在已有的抽象產品中添加其具體產品,支援“開—閉原則”, 然而在添加其抽象產品時,確不支援“開—閉”原則。抽象原廠模式以一種傾斜的 方式支援增加新的產品,它為新產品族的增加提供方便,而不能為新的產品等級 結構的增加提供這樣的方便。

【抽象原廠模式與其它模式】

單例模式(singleton模式):具體工廠類可以設計成單例類,由於工廠通常有一個就可以,因此具體工廠子類一般都實現為一個Singleton。

Factory 方法模式(factory method模式):抽象工廠建立產品的方法定義為Factory 方法。

原型模式(prototype模式):如果有多個可能的產品系列,具體的工廠也可以使用原型模式,具體工廠使用產品系列中。

每一個產品的原型進行執行個體化並且通過複製它的原型來建立新的產品。

【抽象原廠模式PHP樣本】

複製代碼 代碼如下:
<?php
/**
* 抽象原廠模式 2010-05-28 sz
* @author phppan.p#gmail.com
* @package design pattern
*/

/**
* 抽象工廠
*/
interface AbstractFactory {
/**
* 建立等級結構為A的產品的Factory 方法
*/
public function createProductA();

/**
* 建立等級結構為B的產品的Factory 方法
*/
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();
}
}

/**
* 抽象產品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;
}
}


/**
* 用戶端
*/
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(), '
';
echo $productB->getName(), '
';
}

}

Client::main();
?>


Factory 方法模式與抽象原廠模式的不同

Factory 方法模式:
一個抽象產品類,可以派生出多個具體產品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類只能建立一個具體產品類的執行個體。

抽象原廠模式:
多個抽象產品類,每個抽象產品類可以派生出多個具體產品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類可以建立多個具體產品類的執行個體。

區別:
Factory 方法模式只有一個抽象產品類,而抽象原廠模式有多個。
Factory 方法模式的具體工廠類只能建立一個具體產品類的執行個體,而抽象原廠模式可以建立多個。
 

Factory 方法模式與抽象原廠模式

抽象工廠:比原廠模式更深一層,這回連工廠的實作類別都不知道了,不同的人可以拿到不同的工廠類。所以抽象工廠類其實是一個做工廠的工廠類,可以產生出不同的工廠類。
簡單的說如果把“用工廠產生對象”這層關係當做一級產生關係,那麼抽象Factory 方法就是擁有二級產生關係的Factory 方法。如果實際環境更複雜,可以三級 甚至 四級,所以你別想的太複雜,就這麼簡單。
設計模式這本書寫的不錯,不過請啟發性的看他,別深究,因為:
設計模式成書較早那個時候程式員對程式的理解還保持在代碼能編譯通過就好,所以你會發現有很多特性在現在看起來很白癡,似乎根本不用說,我們平時就這麼用的,這是因為你是站在工業時代看石器時代的產品,所以不必一定要用某些模式
設計模式並不針對java語言,所以有些特性你根本就用不到
實際工作中遇到的情況遠比設計模式中提到的情況簡單,有些模式很水你根本用不上,不必深究

這本書最好的方法就是快速通讀,不是叫你跳著讀,還是耐心讀,只是別鑽牛角尖,正常讀,別停。看完後你不會有多牛逼,但是你再未來的幾年開發工作之後回頭過來看有很多不理解的自然就通了,在以後的開發過程中偶爾也會對你寫代碼的過程有一些啟發。

 

http://www.bkjia.com/PHPjc/892262.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/892262.htmlTechArticlePHP實現設計模式中的抽象原廠模式詳解,設計模式詳解 抽象原廠模式(Abstact Factory)是一種常見的軟體設計模式。該模式為一個產品族提供...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.