程式碼設計模式之工廠方法模式(Factory Method)
特點:
工廠方法是粒度很小的設計模式,因為模式的表現只是一個抽象的方法。提前定義用於建立物件的介面,讓子類決定例項化具體的某一個類,即在工廠和產品中間增加介面,工廠不再負責產品的建立,由介面針對不同條件返回具體的類例項,由具體類例項去實現。工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先完全實現‘開-閉原則’,實現了可擴充套件。其次實現更復雜的層次結構,可以應用於產品結果複雜的場合。工廠方法模式是對簡單工廠模式進行了抽象。有一個抽象的Factory類(可以是抽象類和介面),這個類將不在負責具體的產品生產,而是隻制定一些規範,具體的生產工作由其子類去完成。在這個模式中,工廠類和產品類往往可以依次對應。即一個抽象工廠對應一個抽象產品,一個具體工廠對應一個具體產品,這個具體的工廠就負責生產對應的產品。
優點:
工廠方法模式是為了克服簡單工廠模式的缺點(主要是為了滿足OCP)而設計出來的。簡單工廠模式的工廠類隨著產品類的增加需要增加很多方法(或程式碼),而工廠方法模式每個具體工廠類只完成單一任務,程式碼簡潔。工廠方法模式完全滿足OCP,即它有非常良好的擴充套件性。
缺點:
當產品有複雜的多層等級結構時,工廠類只有自己,以不變應萬變,就是模式的缺點。因為工廠類集中了所有產品建立邏輯,一旦不能正常工作,整個系統都要受到影響。系統擴充套件困難,一旦新增新產品就不得不修改工廠邏輯,有可能造成工廠邏輯過於複雜,違背了"開放--封閉"原則(OCP).另外,簡單工廠模式通常使用靜態工廠方法,這使得無法由子類繼承,造成工廠角色無法形成基於繼承的等級結構。
適用範圍:
當一個類不知道它所必須建立物件的類或一個類希望由子類來指定它所建立的物件時,當類將建立物件的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一資訊區域性化的時候,可以使用工廠方法。
例子:
使用者打電話到總代理(在國外),說定製一輛寶馬,總代理回覆說,請問你在哪裡提車,客戶告訴總代理,在上海。總代理告訴客戶並給客戶上海製造商的地址,直接到上海提車即可,而不用到總代理這裡來領車。
這裡其實就是想說明工廠方法的特點:一個具體工廠對應一個具體產品。即上海BWM廠商,直接生產寶馬,使用者直到過來提車即可,根本不需要與總代理打交道。
類圖:
工廠方法類:
factory.h
/**************************************************************
filename : car.h
author: fengsh
QQ:19985430
blog :http://blog.csdn.net/fengsh998
Factory Method Demo
*************************************************************/
#ifndef FACTORY_H
#define FACTORY_H
#include "car.h"
class Factory
{
public:
Factory(void);
~Factory(void);
virtual Car* getCar()=0;
};
class BmwCarFactory : public Factory
{
public:
BmwCarFactory();
~BmwCarFactory();
Car* getCar();
};
class ProscheCarFactory : public Factory
{
public:
ProscheCarFactory();
~ProscheCarFactory();
Car* getCar();
};
#endif
factory.cpp
#include "StdAfx.h"
#include "factory.h"
Factory::Factory(void)
{
}
Factory::~Factory(void)
{
}
//BmwCarFactory class
BmwCarFactory::BmwCarFactory()
{
}
BmwCarFactory::~BmwCarFactory()
{
}
Car* BmwCarFactory::getCar()
{
return new BMWCarProductor();
}
//ProscheCarFactory class
ProscheCarFactory::ProscheCarFactory()
{
}
ProscheCarFactory::~ProscheCarFactory()
{
}
Car* ProscheCarFactory::getCar()
{
return new PorscheCarProductor();
}
製造商類
car.h
/**************************************************************
filename : car.h
author: fengsh
QQ:19985430
blog :http://blog.csdn.net/fengsh998
*************************************************************/
#ifndef CAR_H
#define CAR_H
#include "string"
class Car
{
public:
Car(void);
~Car(void);
virtual void viewEngine() = 0;
virtual void carStart() = 0;
virtual void carStop() = 0;
};
class BMWCarProductor : public Car
{
public:
BMWCarProductor();
~BMWCarProductor();
void viewEngine();
void carStart();
void carStop();
private:
std::string m_engine;
};
class PorscheCarProductor : public Car
{
public:
PorscheCarProductor();
~PorscheCarProductor();
void viewEngine();
void carStart();
void carStop();
private:
std::string m_engine;
};
#endif
car.cpp
#include "StdAfx.h"
#include "car.h"
#include "iostream"
Car::Car(void)
{
}
Car::~Car(void)
{
}
BMWCarProductor::BMWCarProductor()
{
this->m_engine = "BMW";
}
BMWCarProductor::~BMWCarProductor()
{
}
void BMWCarProductor::viewEngine()
{
std::cout<<"The engine is "<<this->m_engine<<std::endl;
}
void BMWCarProductor::carStart()
{
std::cout<<"The BMW Start."<<std::endl;
}
void BMWCarProductor::carStop()
{
std::cout<<"The BMW Stop."<<std::endl;
}
PorscheCarProductor::PorscheCarProductor()
{
this->m_engine = "Porsche";
}
PorscheCarProductor::~PorscheCarProductor()
{
}
void PorscheCarProductor::viewEngine()
{
std::cout<<"The engine is "<<this->m_engine<<std::endl;
}
void PorscheCarProductor::carStart()
{
std::cout<<"The Porsche Start."<<std::endl;
}
void PorscheCarProductor::carStop()
{
std::cout<<"The Porsche Stop."<<std::endl;
}
客戶呼叫演示:
#include "stdafx.h"
#include "stdlib.h"
#include "factory.h"
int _tmain(int argc, _TCHAR* argv[])
{
BmwCarFactory* bc = new BmwCarFactory();
Car* bmw = bc->getCar();
bmw->viewEngine();
bmw->carStart();
bmw->carStop();
ProscheCarFactory* pc = new ProscheCarFactory();
Car* prosche = pc->getCar();
prosche->viewEngine();
prosche->carStart();
prosche->carStop();
system("pause");
return 0;
}