1. 程式人生 > >設計模式(2)- 抽象工廠(Abstract Factory)

設計模式(2)- 抽象工廠(Abstract Factory)

描述:
     抽象工廠是一個適用於建立一系列相關的產品的建立性模型.比如設計模式書中經常講的那個例子-支援多視感視窗的工具包,比如windows和motif風格,這個是風格族.每種風格下面都有些標準的產品族,象BUTTON, TextBox, ListBox等.試想一下,如果直接在client中指定具體產品和它的風格,那麼會出現2*3 = 6中組合,如果新增一種產品或風格,那麼組合會以倍數增加,看來這樣的做法是很愚蠢的.所以還是以面向物件的幾個原則來分析一下這個問題,首先可以看出此問題有兩個方面的變化,一個是視窗風格的變化,另一個是產品的變化.而且在程式中一般都會出現相同風格的產品,windows風格的應用程式絕對不會出現一個motif風格的按鈕.上面的兩點足以說明,客戶端只需要指定一個風格,然後建立時就自然的創建出這個風格的產品族來了.而每種產品應該有個一致的介面,不會因為風格的不同介面也不同.所以客戶端得到的產品不管是什麼風格的都會一致的對待.


靜態結構圖:

這個模式的好處:
增加一個產品,只需增加一個抽象產品類和各個風格的這個產品的具體類.而對別的沒有影響.
增加一個風格,首先要增加一個具體工廠類,然後在每個產品中增加一個支援這個風格的具體產品類.
鬆散了client直接建立產品帶來的耦合性,和複雜性(因為直接建立產品將會得到乘積數量的產品).

什麼時候使用:
一個系統要獨立於它的產品的建立,組合和使用時.
一個系統有一系列產品,而每個產品都有不同的實現(風格),而在一個具體的應用中只能配置一種實現時(風格).

例子:
麥當勞和肯德基都是做快餐的,假如你現在你要做一個這樣的企業的MIS系統,你必須讓這個系統通用,而且這樣的公司都有一系列的相關產品所以你會考慮用抽象工廠來建立產品系列(象漢堡,可樂等),其中公司就是風格族,做的那些食品就是產品族.而且在一個應用中只有同一個風格的產品出現.不會出現肯德基的瓶子裡裝的是麥當勞的可樂.下面是示意程式碼:

// Abstract Factory
class FoodFactory
{
 virtual Homburg* CreateHomburg() = 0;
    virtual Kele* CreateKele() = 0;
}

// Concrete Factory
class KFCFactory : public FoodFactory
{
    Homburg* CreateHomburg()
 {
  cout << "use KFC factory create Homburg" << endl;
  return  new KFCHomburg;
 }

    Kele* CreateKele()
 {
  cout << "use KFC factory create Kele" << endl;
  return  new KFCKele;
 }
}

// Concrete Factory
class MDLFactory : public FoodFactory
{
    Homburg* CreateHomburg()
 {
  cout << "use MDL factory create Homburg" << endl;
  return  new MDLHomburg;
 }

    Kele* CreateKele()
 {
  cout << "use MDL factory create Kele" << endl;
  return  new MDLKele;
 }
}

// abstract Homburg
class Homburg
{
 virtual int  GetFlavour() = 0;
 virtual void DrawMe() = 0;
}

// Concrete Homburg
class KFCHomburg : public Homburg
{
 virtual int  GetFlavour()
 {
  cout << "KFC Homburg very good!" << endl;
  return 80;
 }
   
 virtual void DrawMe()
 {
  cout << "KFC Homburg drawing" << endl;
 }
}

// Concrete Homburg
class MDLHomburg : public Homburg
{
 virtual int  GetFlavour()
 {
  cout << "MDL Homburg better!" << endl;
  return 90;
 }
   
 virtual void DrawMe()
 {
  cout << "MDL Homburg drawing" << endl;
 }
}

//Abstract Kele
class Kele
{
 virtual void AddIce() = 0 ;
 virtual DrawMe() = 0;
}

// Concrete Kele
class KFCKele : public Kele
{
 virtual void AddIce()
 {
  cout << "KFC Kele Add Ice" << endl;
 }
 virtual DrawMe()
 {
  cout << "KFC Kele drawing" << endl;
 }
}

// Concrete Kele
class MDLKele : public Kele
{
 virtual void AddIce()
 {
  cout << "MDL Kele Add Ice" << endl;
 }
 virtual DrawMe()
 {
  cout << "MDL Kele drawing" << endl;
 }
}

int main(int argc, char* argv[])
{
    FoodFactory* foodFactory = new  KFCFactory;
    Homburg* homb =  foodFactory->CreateHomburg();
    Kele*  kele = foodFactory->CreateKele();
    cout << homb->GetFlavour()<< endl;
    homb->DrawMe();
    kele->AddIce();
    kele->DrawMe();
    return 0;
}

相關別的模式:
前面說過的工廠方法和抽象工廠的區別是什麼,各適用於什麼場景中.
如果有一系列產品族則用抽象工廠,如果只有一種型別的產品則用工廠方法.

參考文獻:
《設計模式精解》清華大學出版社,熊傑譯。
《設計模式可複用面向物件軟體的基礎》機械工業出版社,四人團著。