工廠模式背景
日常生活中的工廠,通常是指擁有機器、設備構成的生產線,用以批量製造產生貨物。軟件設計中,也可以使用類似的方法,使用”工廠”批量生產”貨物”。在飛車遊戲中,若玩家飛車撞毀時,需要申請一輛新的飛車繼續用,如此不斷生產–銷燬–再生產同類產品,與此同時,玩家在申請新的飛車時,也可以根據喜好選擇不同類型,如“X7”、”Q5”等等,在選擇型號即可, 這這裏選擇型號申請飛車的過程與生活中的工廠行爲極爲類似,可以試着模擬日常工廠行爲進行類的實現。針對這種實際情況,軟件工程提出了工廠模式,爲創建對象提供了方法。
工廠模式根據實現層次不同,分爲簡單工廠模式(Simple Factory) 和工廠方法模式(Factory Method)。
簡單工廠模式(Simple Factory)
簡單工廠模式使用一個Factory類負責所有產品的創建,實現使用端和生產端分離,使用者不必關心產品的具體創建過程,只需要調用簡單工廠類的Create方法獲得想要的產品即可。
- 簡單工廠模式UML圖
- 簡單工廠模式代碼示例
class Car
{
public:
Car(){};
virtual ~Car(){};
public:
virtual void Drive() = 0;
};
class ConcreteCarA: public Car
{
public:
ConcreteCarA(){}
~ContreteCarA(){}
public:
virtual void Drive(){
//car A drive
}
};
class ConcreteCarB: public Car
{
public:
ConcreteCarB(){}
~ContreteCarB(){}
public:
virtual void Drive(){
//car A drive
}
};
//simple factory
class CarFactory
{
public:
CarFactory(){}
~CarFactory(){}
private:
Car *m_pCarInstance = NULL;
public:
virtual Car* CreateCar(CarType type)
{
if(type == Car_A)
m_pCarInstance = ConcreteCarA();
else if(type == Car_B)
m_pCarInstance ConcreteCarB();
return m_pCarInstance;
}
};
//客戶端使用
Factory* m_pFactory = new CarFactory(); //建造工廠
Car* m_pCarA = m_pFactory->CreateCar(Car_A); //生產A
Car* m_pCarB = m_pFactory->CreateCar(Car_B); //生產B
但是,簡單工廠模式違背了嚴格意義上的“開放封閉原則”,造成如果有一款新的產品增加就必須修改Factory類的源代碼,將新產品加入簡單工廠的創建邏輯,提供給使用者調用。
工廠方法模式(Factory Method)
工廠方法模式定義一個創建產品對象的工廠接口IFactory,將實際創建工作推遲到具體實現的子類當中,核心工廠類不再負責產品的創建,成爲一個抽象工廠角色,僅負責具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可以使系統在不修改具體工廠角色的情況下引進新的產品。
工廠方法法模式是在簡單工廠模式的基礎上進一步抽象產生,使用了抽象工廠角色和麪向對象的多態性,所有具體的工廠子類都必須實現這個接口。當系統擴展需要添加新的產品對象時,僅僅需要添加一個具體對象以及生產該具體對象的對象工廠,原有工廠類不需要進行任何修改,不影響是使用者。該模式不僅保持了簡單工廠模式的優點,而且克服了簡單工廠模式違背“開放封閉原則”的缺點。
- 工廠方法模式UML圖
- 工廠方法模式代碼示例
class CarFactory
{
public:
CarFactory(){}
virtual ~CarFactory(){}
public:
virtual Car* CreateCar() = 0;
};
class ConcreteCarFactoryA : public CarFactory
{
public:
ConcreteCarFactoryA(){}
~ConcreteCarFactoryA(){}
private:
Car* m_pCarInstance;
public:
Car* CreateCar()
{
if(m_pCarInstance == NULL)
m_pCarInstance = new ConcreteCarA();
return m_pCarInstance;
}
};
class ConcreteCarFactoryB : public CarFactory
{
public:
ConcreteCarFactoryB(){}
~ConcreteCarFactoryB(){}
private:
Car* m_pCarInstance;
public:
Car* CreateCar()
{
if(m_pCarInstance == NULL)
m_pCarInstance = new ConcreteCarB();
return m_pCarInstance;
}
};
//客戶端使用
//create FactoryA to generate Car A
Factory* m_pFactoryA = new ConcreteCarFactoryA(); //建造具體工廠A
Car* m_pCarA = m_pFactoryA->CreateCar(); //生產A
//create FactoryB to generate Car B
Factory* m_pFactoryB = new ConcreteCarFactoryB(); //建造具體工廠B
Car* m_pCarB =m_pFactoryA->CreateCar(); //生產B
工廠方法模式的不足之處在於: 使用者根據需要決定實例化哪一個具體的工廠,相當於把簡單工廠模式的內部判斷邏輯轉移到了客戶端代碼。此外,該模式需要增加額外的代碼,引起代碼工作量的增加。