04:工廠模式——C++實現
目錄
一、簡介
工廠模式(Factory Pattern):定義一個建立物件的介面,讓其子類自己決定例項化哪一個工廠類,工廠模式使其建立過程延遲到子類進行。主要解決介面選擇的問題。此模式的核心思想是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦、複用以及方便後期維護拓展的目的。“工廠方法模式”是“簡單工廠模式”的進一步抽象和推廣。工廠模式基本和簡單工廠模式差不多,簡單工廠模式 - 在產品子類新增時,需要新增一個判斷分支,這違背了開放-封閉原則。因此,工廠模式就是為了解決這個問題而產生的。
二、應用場景
當我們明確地計劃不同條件下建立不同例項時。如:
1、日誌記錄器:記錄可能記錄到本地硬碟、系統事件、遠端伺服器等,使用者可以選擇記錄日誌到什麼地方。
2、資料庫訪問,當用戶不知道最後系統採用哪一類資料庫,以及資料庫可能有變化時。
3、設計一個連線伺服器的框架,需要三個協議,"POP3"、"IMAP"、"HTTP",可以把這三個作為產品類,共同實現一個介面。
三、要點
作為一種建立類模式,在任何需要生成複雜物件的地方,都可以使用工廠方法模式。有一點需要注意的地方就是複雜物件適合使用工廠模式,而簡單物件,特別是只需要通過 new 就可以完成建立的物件,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的複雜度。
四、樣例
Factory(抽象工廠):是工廠方法模式的核心,與應用程式無關。任何在模式中建立的物件的工廠類必須實現這個介面。
ConcreteFactory(具體工廠):實現抽象工廠介面的具體工廠類,包含與應用程式密切相關的邏輯,並且被應用程式呼叫以建立產品物件。
Product(抽象產品):所建立物件的基類,也就是具體產品的共同父類或共同擁有的介面。
ConcreteProduct(具體產品):實現了抽象產品角色所定義的介面。某具體產品有專門的具體工廠建立,它們之間往往一一對應。
1、建立抽象產品
// product.h #ifndef PRODUCT_H #define PRODUCT_H #include <string> using namespace std; // 汽車介面 class ICar { public: virtual string Name() = 0; // 汽車名稱 }; #endif
2、建立具體產品
// concrete_product.h
#ifndef CONCRETE_PRODUCT_H
#define CONCRETE_PRODUCT_H
#include "product.h"
class BenzCar :public ICar
{
public:
string Name() {
return "Benz Car";
}
};
class BMWCar :public ICar
{
public:
string Name() {
return "BMW Car";
}
};
class AudiCar :public ICar
{
public:
string Name() {
return "Audi Car";
}
};
#endif
3、建立抽象工廠
// factory.h
#ifndef FACTORY_H
#define FACTORY_H
#include "product.h"
// 工廠介面
class AFactory
{
public:
virtual ICar* CreateCar() = 0; // 生成汽車
};
#endif
4、建立具體工廠
// concrete_factory.h
#ifndef CONCRETE_FACTORY_H
#define CONCRETE_FACTORY_H
#include "factory.h"
#include "concrete_product.h"
class BenzFactory :public AFactory
{
public:
ICar* CreateCar() {
return new BenzCar();
}
};
class BMWFactory :public AFactory
{
public:
ICar* CreateCar() {
return new BMWCar();
}
};
class AudiFactory :public AFactory
{
public:
ICar* CreateCar() {
return new AudiCar();
}
};
#endif
5、客戶端程式
// concrete_factory.h
#ifndef CONCRETE_FACTORY_H
#define CONCRETE_FACTORY_H
#include "factory.h"
#include "concrete_product.h"
class BenzFactory :public AFactory
{
public:
ICar* CreateCar() {
return new BenzCar();
}
};
class BMWFactory :public AFactory
{
public:
ICar* CreateCar() {
return new BMWCar();
}
};
class AudiFactory :public AFactory
{
public:
ICar* CreateCar() {
return new AudiCar();
}
};
#endif
6、輸出:
Benz factory : Benz Car
Bmw factory : Bmw Car
Audi factory : Audi Car
五、優缺點
優點:
1、一個呼叫者想建立一個物件,只要知道其名稱就可以了。
2、擴充套件性高,如果想增加一個產品,只要擴充套件一個工廠類就可以。
3、遮蔽產品的具體實現,呼叫者只關心產品的介面。
缺點:
每次增加一個產品時,都需要增加一個具體類和物件實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。