文章出處

示例代碼詳見https://github.com/52fhy/design_patterns

抽象工廠

抽象工廠(Abstract Factory)是應對產品族概念的。比如說,每個汽車公司可能要同時生產轎車、跑車、貨車、客車,那么每一個工廠都要有創建轎車,貨車和客車的方法。

在學習抽象工廠具體實例之前,應該明白兩個重要的概念:產品族產品等級

產品等級:同一個產品的不同分類或者組成。
產品族:是指位于不同產品等級結構中,功能相關聯的產品組成的家族。

例如:汽車分奔馳、寶馬,奔馳下面還有跑車、MINI車等等。其中奔馳就是產品族,跑車、MINI車是產品等級。

再例如:AMD的主板、芯片組、CPU組成一個家族,Intel的主板、芯片組、CPU組成一個家族。而這兩個家族都來自于三個產品等級:主板、芯片組、CPU。

抽象工廠是汽車生產工廠的抽象,工廠方法是一個汽車工廠里每種汽車型號的抽象;簡單工廠和抽象工廠含義一樣,只是產品型號是固定的。

應對產品族概念而生,增加新的產品線很容易,但是無法增加新的產品。

抽象工廠UML圖:

簡單工廠需要有4個角色:

  • Product接口類:用于定義產品規范,例如ProductA、ProductB,抽象工廠有多個Product接口類;
  • 具體的產品實現,例如ProductA1、ProductA2;
  • 抽象工廠類IFactory:用于規范每個工廠;
  • 具體產品族創建的工廠,例如Factory1、Factory2。

對應到汽車工廠的例子,這么解釋:
1、汽車廠(抽象工廠)分為奔馳汽車廠(F1)、寶馬汽車廠(F2);
2、每個汽車廠都能生產:跑車(ProductA)、Mini車(ProductB);
3、可以有產品:奔馳跑車(A1)、寶馬跑車(A2)、奔馳MINI(B1)、寶馬MINI(B2);
4、那么奔馳汽車廠(F1)可以生產奔馳跑車(A1)、奔馳MINI(B1);
5、跑車(ProductA)、Mini車(ProductB)可以有自己的一些行為(operation):例如driver()playMusic()

其中:奔馳車、寶馬車就是產品族,跑車、MINI車是產品等級。

對應到芯片工廠的例子,這么解釋:
1、芯片廠商(抽象工廠)分為Intel廠(F1)、AMD廠(F2);
2、每個芯片廠商都能生產:CPU(ProductA)、Mainboard(ProductB);
3、可以有產品:Intel CPU(A1)、AMD CPU(A2)、Intel主板(B1)、AMD主板(B2);
4、那么Intel廠(F1)可以生產Intel CPU(A1)、Intel主板(B1);
5、CPU(ProductA)、Mainboard(ProductB)可以有自己的一些行為(operation):例如compute()installCPU()

下面以汽車生產為例:
跑車:

namespace Yjc\AbstractFactory;

interface IProductSportCar
{
    public function driver();
}

MINI車:

namespace Yjc\AbstractFactory;

interface IProductMiniCar
{
    public function driver();
    public function playMusic();
}

實現的跑車產品:

namespace Yjc\AbstractFactory;

class BenzSport implements IProductSportCar
{
    public function driver()
    {
        echo 'driver';
    }
}

class BmwSport implements IProductSportCar
{
    public function driver()
    {
        echo 'driver';
    }
}

實現的MINI車產品:

namespace Yjc\AbstractFactory;

class BenzMini implements IProductMiniCar
{
    public function driver()
    {
        echo 'driver';
    }

    public function playMusic()
    {
        echo 'playMusic';
    }
}

class BmwMini implements IProductMiniCar
{
    public function driver()
    {
        echo 'driver';
    }

    public function playMusic()
    {
        echo 'playMusic';
    }
}

抽象工廠(能生產各種類型車):

namespace Yjc\AbstractFactory;

interface IFactory
{
    public function makeMiniCar();//Mini車
    public function makeSportCar();//跑車
}

抽象工廠實現:

namespace Yjc\AbstractFactory;

//寶馬工廠
class FactoryBmw implements IFactory
{

    public function makeMiniCar()
    {
        return new BmwMini();
    }

    public function makeSportCar()
    {
        return new BmwSport();
    }
}

//奔馳工廠
class FactoryBenz implements IFactory
{

    public function makeMiniCar()
    {
        return new BenzMini();
    }

    public function makeSportCar()
    {
        return new BenzSport();
    }
}

測試:

//生產奔馳跑車
$benzFactory = new FactoryBenz();
$benzCar = $benzFactory->makeSportCar();
$benzCar->driver();

//生產寶馬MINI
$bmwFactory = new FactoryBmw();
$bmwCar = $bmwFactory->makeMiniCar();
$bmwCar->playMusic();

簡單工廠、工廠方法、抽象工廠總結:

  • 簡單工廠: 用來生產同一等級結構中的任意產品。(對于增加新的產品,無能為力)
  • 工廠方法:用來生產同一等級結構中的固定產品。(支持增加任意產品)
  • 抽象工廠:用來生產不同產品族的全部產品。(對于增加新的產品,無能為力;支持增加產品族)

以上三種工廠方法在等級結構和產品族這兩個方向上的支持程度不同。所以要根據情況考慮應該使用哪種方法。

參考:
1、設計模式:簡單工廠、工廠方法、抽象工廠之小結與區別 - superbeck的專欄 - 博客頻道 - CSDN.NET
http://blog.csdn.net/superbeck/article/details/4446177
2、《JAVA與模式》之抽象工廠模式 - java_my_life - 博客園
http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()