天天看點

設計模式(五)抽象工廠 C++

每一個設計模式的産生都是 為了應對某些應用場景。

        簡單工廠可以由一個工廠生産不同的産品,缺點是如果不斷增加産品,則需要不斷修改工廠,違反了開放封閉原則,(類、子產品、函數可以擴充,但是不可以修改)。

        于是,就出現了工廠方法模式。所謂工廠方法模式,是指定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類。打個比方

現在有A、B兩種産品,那麼久開兩個工廠。工廠A負責生産A産品,工廠B負責生産B種産品。這時候客戶不需要告訴工廠生産哪種産品了。需要A産品,直接通知A工廠就好了,需要B産品,直接通知B工廠就好了。工廠方法和簡單工廠的差別,在于開放封閉原則。

        但是随着業務的變化,設計模式可能也需要随着變化。比如說,我們為客戶安裝了一個MySQL資料庫,裡面有兩張表,UserTable(使用者表)和ApartmentTable(部門表),但是未來某一天使用者可能會用Access來存放這兩張表,怎麼辦?工廠方法?但是工廠方法是一對一的,一個工廠生産一個産品,在這裡如果說把MySQL下的User表作為一個産品,然後為MySQL下的User表建立一個工廠?這樣一來在整個過程中會有四個工廠。為每張表建立一個工廠也能夠解決問題,但是這不是最好的方法。因為無論兩個資料庫下的兩張User表,還是Apartment表還是有相似性的,換句話說需要建立的對象是一系列互相關聯或互相依賴的産品族,能不能根據這些相似性進行抽象呢?

這個時候要考慮抽象工廠模式。還是開設兩家工廠,工廠A負責生産A1 、A2型号産品,B工廠負責生産B1、B2型号的産品。  

在這個業務場景下就是兩個資料工廠,MySQL生産AccessUser,AccessApartment,Access生産 AccessUser ,AccessApartment。

代碼實作如下

#include <iostream>    
#include <windows.h>
using namespace std;

//定義抽象類(使用者表) 
class productUserTable
{
public:
  virtual void show() = 0;
};

//定義抽象類 (部門表) 
class productAprtmentTable
{
public:
  virtual void show() = 0;
};

// 資料庫抽象類作為抽象工廠
class FactoryDB
{
public:
  virtual productUserTable *CreateUserTable() = 0;
  virtual productAprtmentTable *CreateApartmentTable() = 0;
};

//定義具體類  ,具體的使用者表
class MySQLUserTable :public productUserTable
{
public:
  void show() 
  { 
    cout << "product MySQLUserTable" << endl; 
  }
};

class AccessUserTable :public productUserTable
{
public:
  void show() 
  { 
    cout << "product AccessUserTable" << endl;
  }
};

//定義具體類 ,具體的産品表 
class MySQLAprtmentTable :public productAprtmentTable
{
public:
  void show() 
  { 
    cout << "product MySQLAprtmentTable" << endl; 
  }
};

class AccessAprtmentTable :public productAprtmentTable
{
public:
  void show()
  { 
    cout << "product AccessAprtmentTable" << endl; 
  }
};

// MySQL資料庫下的 User 表、Apartment表、是以MySQL為目前工廠
class FactoryMySQL:public FactoryDB
{
public:
  productUserTable *CreateUserTable() 
  { 
    return new MySQLUserTable();
  }
  productAprtmentTable *CreateApartmentTable()
  { 
    return new MySQLAprtmentTable(); 
  }
};

// Access資料庫下的 User 表、Apartment表,是以Access為目前工廠
class FactoryAccess :public FactoryDB
{
public:
  productUserTable *CreateUserTable() 
  { 
    return new AccessUserTable();
  }
  productAprtmentTable *CreateApartmentTable()
  { 
    return new AccessAprtmentTable();
  }
};

int main()
{
  FactoryMySQL *factoryA = new FactoryMySQL();
  factoryA->CreateUserTable()->show();
  factoryA->CreateApartmentTable()->show();

  FactoryAccess *factoryB = new FactoryAccess();
  factoryB->CreateUserTable()->show();
  factoryB->CreateApartmentTable()->show();

  system("pause");
  return 0;
}      

抽象工廠模式的優點

抽象工廠模式除了具有工廠方法模式的優點外,最主要的優點就是可以在類的内部對産品族進行限制。所謂的産品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類内部對産品族的關聯關系進行定義和描述,而不必專門引入一個新的類來進行管理。

抽象工廠模式的缺點

産品族的擴充将是一件十分費力的事情,假如産品族中需要增加一個新的産品,則幾乎所有的工廠類都需要進行修改。是以使用抽象工廠模式時,對産品等級結構的劃分是非常重要的。

适用場景

當需要建立的對象是一系列互相關聯或互相依賴的産品族時,便可以使用抽象工廠模式。說的更明白一點,就是一個繼承體系中,如果存在着多個等級結構(即存在着多個抽象類),并且分屬各個等級結構中的實作類之間存在着一定的關聯或者限制,就可以使用抽象工廠模式。假如各個等級結構中的實作類之間不存在關聯或限制,則使用多個獨立的工廠來對産品進行建立,則更合适一點。

繼續閱讀