工廠方法是一種對象創建型模式,它的目的是定義一個用於創建對象的接口,讓子類決定實例化哪一個類,可以使一個類的實例化延遲到子類。
適用場景
工廠方法適用於一下幾種情況:
1)當一個類不知道它所必須創建的對象的類的時候;
2)當一個類希望由它的子類來指定它所創建的對象的時候;
3)當類將創建對象的職責委托給多個幫助子類中的一個;
模式結構
下面我們來看一下工廠方法的模式結構以便對其有一個全局的了解,如圖所示:
參與者
很顯然,從上面的模式結構中我們可以看出工廠方法主要有4個主要參與者。
1)Product
定義工廠方法所創建對象的接口。
2)concreteProduct
實現對象創建的接口。
3)Creator
聲明工廠方法以返回Product對象,也可以定義缺省的實現,返回一個缺省的ConcreteProduct對象,另外在Creator中也可以調用工廠方法以創建一個Product對象,稍後在代碼中有體現,具體主要GetProduct()方法和CreateProduct()方法。
4)ConcreteCreator
重定義CreateProduct()方法返回一個具體的ConcreteProduct實例。
另外,Creator如果想創建一個具體的ConcreteProduct實例,則依賴於它的子類,如ConcreteCreator,這樣就造成一個潛在的問題--可能僅為了創建適當的Product對象而被迫創建Creator類的子類,在C++中的一種解決方案是使用模板。
實現
下面通過代碼實現上述工廠方法,類中具體的操作與上圖有出入,主要為體現這種思想--延遲創建。
首先是各類的聲明以及繼承體系:
[cpp] //factory.h
#ifndef FACTORY_H
#define FACTORY_H
class Product
{
};
class Creator
{
public:
Creator():m_pProduct(nullptr){};
Product* GetProduct();
virtual Product* CreateProduct()=0;
private:
Product *m_pProduct;
};
/*針對上述潛在問題,這裡提供一種解決方案
*1)提供一個Creator類的模板子類,用Product類作為模板參數
*2)這樣做可以減少類的創建
*/
template <class TheProduct>
class StandardCreator:public Creator
{
public:
virtual Product* CreateProduct();
};
template <typename TheProduct>
Product* StandardCreator<TheProduct>::CreateProduct()
{
return new TheProduct();
}
#endif
//factory.h
#ifndef FACTORY_H
#define FACTORY_H
class Product
{
};
class Creator
{
public:
Creator():m_pProduct(nullptr){};
Product* GetProduct();
virtual Product* CreateProduct()=0;
private:
Product *m_pProduct;
};
/*針對上述潛在問題,這裡提供一種解決方案
*1)提供一個Creator類的模板子類,用Product類作為模板參數
*2)這樣做可以減少類的創建
*/
template <class TheProduct>
class StandardCreator:public Creator
{
public:
virtual Product* CreateProduct();
};
template <typename TheProduct>
Product* StandardCreator<TheProduct>::CreateProduct()
{
return new TheProduct();
}
#endif
然後是簡單的實現:
[cpp] //factory.cpp
#include "factory.h"
#include <iostream>
using namespace std;
Product* Creator::GetProduct()
{
if (nullptr == m_pProduct)
{
m_pProduct = CreateProduct();
}
return m_pProduct;
}
//factory.cpp
#include "factory.h"
#include <iostream>
using namespace std;
Product* Creator::GetProduct()
{
if (nullptr == m_pProduct)
{
m_pProduct = CreateProduct();
}
return m_pProduct;
}
最後是測試代碼:
[cpp] //test.cpp
#include "factory.h"
#include <iostream>
using namespace std;
//客戶只需提供不同的產品類,便可以使用統一的方法創建產品。
class MyProduct:public Product
{
public:
MyProduct()
{
cout << "MyProduct has been constructed!" << endl;
}
};
class YourProduct:public Product
{
public:
YourProduct()
{
cout << "YourProduct has been constructed!" << endl;
}
};
class OurProduct:public Product
{
public:
OurProduct()
{
cout << "OurProduct has been constructed!" << endl;
}
};
int main()
{
StandardCreator<OurProduct> ourCreator;
Product *pProduct = ourCreator.GetProduct();
StandardCreator<MyProduct> myCreator;
pProduct = myCreator.GetProduct();
StandardCreator<YourProduct> yourCreator;
pProduct = yourCreator.GetProduct();
char ch = getchar();
return 1;
}
//test.cpp
#include "factory.h"
#include <iostream>
using namespace std;
//客戶只需提供不同的產品類,便可以使用統一的方法創建產品。
class MyProduct:public Product
{
public:
MyProduct()
{
cout << "MyProduct has been constructed!" << endl;
}
};
class YourProduct:public Product
{
public:
YourProduct()
{
cout << "YourProduct has been constructed!" << endl;
}
};
class OurProduct:public Product
{
public:
OurProduct()
{
cout << "OurProduct has been constructed!" << endl;
}
};
int main()
{
StandardCreator<OurProduct> ourCreator;
Product *pProduct = ourCreator.GetProduct();
StandardCreator<MyProduct> myCreator;
pProduct = myCreator.GetProduct();
StandardCreator<YourProduct> yourCreator;
pProduct = yourCreator.GetProduct();
char ch = getchar();
return 1;
}
下面是測試效果:www.2cto.com
摘自 Arvon Zhang的專欄