介绍
前文初始篇C++ 深入浅出工厂模式(初始篇),主要阐述了简单工厂模式、工厂方法模式和抽象工厂模式的结构、特点和缺陷等。以上三种方式,在新增产品时,要么修改工厂类,要么需新增具体的工厂类,说明工厂类的封装性还不够好。
本文进阶篇,主要是将工厂类的封装性提高,达到新增产品时,也不需要修改工厂类,不需要新增具体的工厂类。封装性高的工厂类特点是扩展性高、复用性也高。
模板工厂
针对工厂方法模式封装成模板工厂类,那么这样在新增产品时,是不需要新增具体的工厂类,减少了代码的编写量。
UML图:
模板工厂代码:
Shoes和Clothe,分别为鞋子和衣服的抽象类(基类)NiKeShoes和UniqloClothe,分别为耐克鞋子和优衣库衣服具体产品类。
class Shoes
{
public:
virtual void Show() =
0;
virtual ~Shoes() {}
};
class NiKeShoes : public Shoes
{
public:
void Show()
{
std::
cout <<
"我是耐克球鞋,我的广告语:Just do it" <<
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;
}
};
AbstractFactory为抽象模板工厂类,其中模板参数:AbstractProduct_t 产品抽象类,如Shoes、ClotheConcreteFactory为具体模板工厂类,其中模板参数:AbstractProduct_t 产品抽象类(如Shoes、Clothe),ConcreteProduct_t 产品具体类(如NiKeShoes、UniqloClothe)
template <
class AbstractProduct_t>
class AbstractFactory
{
public:
virtual AbstractProduct_t *CreateProduct() =
0;
virtual ~AbstractFactory() {}
};
template <
class AbstractProduct_t, class ConcreteProduct_t>
class ConcreteFactory : public AbstractFactory<AbstractProduct_t>
{
public:
AbstractProduct_t *CreateProduct()
{
return new ConcreteProduct_t();
}
};
main函数,根据不同类型的产品,构造对应的产品的工厂对象,便可通过对应产品的工厂对象创建具体的产品对象。
int main()
{
ConcreteFactory<Shoes, NiKeShoes> nikeFactory;
Shoes *pNiKeShoes = nikeFactory.CreateProduct();
pNiKeShoes->Show();
ConcreteFactory<Clothe, UniqloClothe> uniqloFactory;
Clothe *pUniqloClothe = uniqloFactory.CreateProduct();
pUniqloClothe->Show();
delete pNiKeShoes;
pNiKeShoes =
NULL;
delete pUniqloClothe;
pUniqloClothe =
NULL;
return 0;
}
输出结果:
[root@lincoding factory]# ./templateFactory
我是耐克球鞋,我的广告语:Just do it
我是优衣库衣服,我的广告语:I am Uniqlo
产品注册模板类+单例工厂模板类
前面的模板工厂虽然在新增产品的时候,不需要新增具体的工厂类,但是缺少一个可以统一随时随地获取指定的产品对象的类。
还有改进的空间,我们可以把产品注册的对象用std::map的方式保存,通过key-valve的方式可以轻松简单的获取对应的产品对象实例。
实现大致思路:
把产品注册的功能封装成产品注册模板类。注册的产品对象保存在工厂模板类的std::map,便于产品对象的获取。
把获取产品对象的功能封装成工厂模板类。为了能随时随地获取指定产品对象,则把工厂设计成单例模式。
UML图:
产品注册模板类+单例工厂模板类:
IProductRegistrar为产品注册抽象类,模板参数 ProductType_t 表示的类是产品抽象类(如Shoes、Clothe)。提供了产品对象创建的纯虚函数CreateProduct。ProductFactory为工厂模板类,模板参数 ProductType_t 表示的类是产品抽象类(如Shoes、Clothe)。用于保存注册产品对象到std::map中和获取对应的产品对象。ProductRegistrar为产品注册模板类,模板参数 ProductType_t 表示的类是产品抽象类(如Shoes、Clothe),ProductImpl_t 表示的类是具体产品(如NikeShoes、UniqloClothe)。用于注册产品到工厂类和创建产品实例对象。
template <
class ProductType_t>
class IProductRegistrar
{
public:
virtual ProductType_t *CreateProduct() =
0;
protected:
IProductRegistrar() {}
virtual ~IProductRegistrar() {}
private:
IProductRegistrar(
const IProductRegistrar &);
const IProductRegistrar &
operator=(
const IProductRegistrar &);
};
template <
class 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;
}
ProductType_t *GetProduct(std::string name)
{
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 &);
std::
map<
std::
string, IProductRegistrar<ProductType_t> *> m_ProductRegistry;
};
template <
class ProductType_t, class 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();
}
};
main函数,通过ProductRegistrar注册各种不同类型产品,在统一由ProductFactory单例工厂获取指定的产品对象。
int main()
{
ProductRegistrar<Shoes, NiKeShoes> nikeShoes(
"nike");
Shoes *pNiKeShoes = ProductFactory<Shoes>::Instance().GetProduct(
"nike");
pNiKeShoes->Show();
if (pNiKeShoes)
{
delete pNiKeShoes;
}
ProductRegistrar<Clothe, UniqloClothe> adidasShoes(
"uniqlo");
Clothe *pUniqloClothe = ProductFactory<Clothe>::Instance().GetProduct(
"uniqlo");
pUniqloClothe->Show();
if (pUniqloClothe)
{
delete pUniqloClothe;
}
return 0;
}
输出结果:
[root@lincoding factory]# ./singleFactory
我是耐克球鞋,我的广告语:Just do it
我是优衣库衣服,我的广告语:I am Uniqlo
总结
将工厂方法模式改良成模板工厂,虽然可以解决产品新增时,不需要新增具体工厂类,但是缺少一个可以随时随地获取产品对象的方式,说明还有改进的空间。
将模板工厂改良成产品注册模板类+单例工厂模板类,产品注册模板类用于注册不同类型的产品,单例工厂模板类用于获取指定已注册的产品对象。这种方式,可以把工厂模式中产品的注册和获取的主要功能很好的抽象成两个类,并且使用单例模式使得工厂类可以随时随地获取已注册的产品对象。
所以产品注册模板类+单例工厂模板类的工厂模式,达到了开闭法则,并且扩展性高和封装度高。
PS:想学习更多单例模式,可以参考C++ 线程安全的单例模式总结文章阅读。
标签:
Linux,
C/C++
好文要顶
关注我
收藏该文
小林coding
关注 - 0
粉丝 - 1
+加关注
0
0
« 上一篇:
C++ 深入浅出工厂模式(初识篇)
posted @
2019-09-15 21:38
小林coding 阅读(
17) 评论(
)
编辑
收藏
刷新评论
刷新页面
返回顶部
发表评论
昵称:
评论内容:
[Ctrl+Enter快捷键提交]
【推荐】超50万C++/C#源码: 大型实时仿真组态图形源码
【推荐】零基础轻松玩转华为云产品,获壕礼加返百元大礼
【推荐】天翼云开学季,学生必备云套餐,每月仅需9块9
【推荐】华为云文字识别资源包重磅上市,1元万次限时抢购
【福利】git pull && cherry-pick 博客园&华为云百万代金券
相关博文:
·
欢迎光临博客园
·
设计模式----工厂模式(c++)
·
c++设计模式之工厂模式
·
深入浅出工厂模式
·
Java进阶篇设计模式之二-----工厂模式
最新 IT 新闻:
·
微软Edge团队重新塑造三星Fold等折叠屏手机网页体验
·
Linux Kernel 5.3正式发布:支持Intel Speed Select
·
生命化学分子如何起源于太空?碳分子形成环状化合物
·
外媒:苹果正在变成一家相机公司
·
星际旅行真的可能实现吗?
»
更多新闻...
转载于:https://www.cnblogs.com/ylaoda/p/11525696.html
相关资源:JAVA上百实例源码以及开源项目