C++
#include <iostream>
#include <map>
/***********************/
// 基類 鞋子
class Shoes
{
public:
virtual void Show() = 0;
virtual ~Shoes() {}
};
// 耐克鞋子
class NiKeShoes : public Shoes
{
public:
void Show()
{
std::cout << "我是耐克球鞋,我的廣告語:Just do it" << std::endl;
}
};
// 阿迪鞋子
class AdidasShoes : public Shoes
{
public:
void Show()
{
std::cout << "我是阿迪球鞋,我的廣告語:Impossible is nothing." << std::endl;
}
};
// 基類 衣服
class Clothe
{
public:
virtual void Show() = 0;
virtual ~Clothe() {}
};
// 優衣庫衣服
class UniqloClothe : public Clothe
{
public:
void Show()
{
std::cout << "我是優衣庫衣服,我的廣告語:I am Uniqlo" << std::endl;
}
};
// 盜版衣服
class DaoBanClothe : public Clothe
{
public:
void Show()
{
std::cout << "我是盜版衣,我的廣告語:想怎麼盜版就怎麼盜版。" << std::endl;
}
};
/**************************************/
// 基類,産品注冊模闆接口類
// 模闆參數 ProductType_t 表示的類是産品抽象類
template <typename ProductType_t>
class IProductRegistrar
{
public:
// 擷取産品對象抽象接口
virtual ProductType_t* CreateProduct() = 0;
protected:
// 禁止外部構造和虛構, 子類的"内部"的其他函數可以調用
IProductRegistrar() {}
virtual ~IProductRegistrar() {}
private:
// 禁止外部拷貝和指派操作
IProductRegistrar(const IProductRegistrar&);
const IProductRegistrar& operator=(const IProductRegistrar&);
};
// 工廠模闆類,用于擷取和注冊産品對象
// 模闆參數 ProductType_t 表示的類是産品抽象類
template <typename ProductType_t>
class ProductFactory
{
public:
// 擷取工廠單例,工廠的執行個體是唯一的
static ProductFactory<ProductType_t>& Instance()
{
static ProductFactory<ProductType_t> instance;
return instance;
}
// 産品注冊
void RegisterProduct(IProductRegistrar<ProductType_t>* registrar, std::string name)
{
m_ProductRegistry[name] = registrar;
}
// 根據名字name,擷取對應具體的産品對象
ProductType_t* GetProduct(std::string name)
{
// 從map找到已經注冊過的産品,并傳回産品對象
if (m_ProductRegistry.find(name) != m_ProductRegistry.end())
{
return m_ProductRegistry[name]->CreateProduct();
}
// 未注冊的産品,則報錯未找到
std::cout << "No product found for " << name << std::endl;
return NULL;
}
private:
// 禁止外部構造和虛構
ProductFactory() {}
~ProductFactory() {}
// 禁止外部拷貝和指派操作
ProductFactory(const ProductFactory&);
const ProductFactory& operator=(const ProductFactory&);
// 儲存注冊過的産品,key:産品名字 , value:産品類型
std::map<std::string, IProductRegistrar<ProductType_t>*> m_ProductRegistry;
};
// 産品注冊模闆類,用于建立具體産品和從工廠裡注冊産品
// 模闆參數 ProductType_t 表示的類是産品抽象類(基類),ProductImpl_t 表示的類是具體産品(産品種類的子類)
template <typename ProductType_t, typename ProductImpl_t>
class ProductRegistrar : public IProductRegistrar<ProductType_t>
{
public:
// 構造函數,用于注冊産品到工廠,隻能顯示調用
explicit ProductRegistrar(std::string name)
{
// 通過工廠單例把産品注冊到工廠
ProductFactory<ProductType_t>::Instance().RegisterProduct(this, name);
}
// 建立具體産品對象指針
ProductType_t* CreateProduct()
{
return new ProductImpl_t();
}
};
/***************************************************************/
int main()
{
// ========================== 生産耐克球鞋過程 ===========================//
// 注冊産品種類為Shoes(基類),産品為NiKe(子類)到工廠,産品名為nike
ProductRegistrar<Shoes, NiKeShoes> nikeShoes("nike");
ProductRegistrar<Shoes, AdidasShoes> adidasShoes("adidas"); // 如果相同鍵值,會覆寫前面的。如果還是 nike,會用 adidas 的資訊覆寫掉前面的。
// 從工廠擷取産品種類為Shoes,名稱為nike的産品對象
Shoes* pNiKeShoes = ProductFactory<Shoes>::Instance().GetProduct("nike");
Shoes* pAdidasShoes = ProductFactory<Shoes>::Instance().GetProduct("adidas");
// 顯示産品的廣告語
pNiKeShoes->Show();
pAdidasShoes->Show();
// 釋放資源
if (pNiKeShoes)
{
delete pNiKeShoes;
}
if (pAdidasShoes != nullptr) {
delete pAdidasShoes;
pAdidasShoes = nullptr;
}
std::cout << std::endl;
// ========================== 生産優衣庫衣服過程 ===========================//
// 注冊産品種類為Clothe(基類),産品為UniqloClothe(子類)到工廠,産品名為uniqlo
ProductRegistrar<Clothe, UniqloClothe> uniqloCloth("uniqlo");
ProductRegistrar<Clothe, DaoBanClothe> daobanCloth("daoban");
// 從工廠擷取産品種類為Shoes,名稱為adidas的産品對象
Clothe* pUniqloClothe = ProductFactory<Clothe>::Instance().GetProduct("uniqlo");
Clothe* pDaobanClothe = ProductFactory<Clothe>::Instance().GetProduct("daoban");
// 顯示産品的廣告語
pUniqloClothe->Show();
pDaobanClothe->Show();
// 釋放資源
if (pUniqloClothe)
{
delete pUniqloClothe;
}
if (pDaobanClothe != nullptr) {
delete pDaobanClothe;
pDaobanClothe = nullptr;
}
return 0;
}
輸出:
我是耐克球鞋,我的廣告語:Just do it
我是阿迪球鞋,我的廣告語:Impossible is nothing.
我是優衣庫衣服,我的廣告語:I am Uniqlo
我是盜版衣,我的廣告語:想怎麼盜版就怎麼盜版。
參考: