当前位置: 首页 > Linux

C++简单工厂模式(进阶)

时间:2023-04-07 03:10:39 Linux

上篇入门文章C++简单工厂模式(入门)介绍,主要阐述了简单工厂模式、工厂方法模式和抽象工厂模式的结构、特点和缺陷。以上三种方式,在添加新产品时,要么修改工厂类,要么添加具体的工厂类,可见工厂类的封装性不够好。这篇文章的进阶部分主要是完善工厂类的封装。添加新产品时,无需修改工厂类或添加特定的工厂类。具有高封装性的工厂类具有高可扩展性和高可重用性的特点。工厂方法模式将模板工厂封装成一个模板工厂类,所以在添加新产品时,不需要添加具体的工厂类,减少了代码编写量。UML图:模板工厂代码:Shoes和Clothes,分别是鞋子和衣服的抽象类(基类),NiKeShoes和UniqloClothe,分别是耐克鞋子和优衣库衣服的具体产品类。//基础鞋类Shoes{public:virtualvoidShow()=0;virtual~Shoes(){}};//NikeshoesclassNiKeShoes:publicShoes{public:voidShow(){std::cout<<"IamNikesneakers,myslogan:Justdoit"<classAbstractFactory{public:virtualAbstractProduct_t*CreateProduct()=0;virtual~AbstractFactory(){}};//具体模板工厂类//模板参数:AbstractProduct_t产品抽象类,ConcreteProduct_t产品具体类模板classConcreteFactory:publicAbstractFactory{public:AbstractProduct_t*CreateProduct(){返回新的ConcreteProduct_t();}};main函数,根据不同类型的产品,构造对应产品的工厂对象,然后可以通过对应的产品从工厂对象创建具体的产品对象intmain(){//构造耐克鞋工厂对象ConcreteFactory<鞋子,耐克鞋>nikeFactory;//创建耐克鞋对象Shoes*pNiKeShoes=nikeFactory.CreateProduct();//打印耐克鞋广告pNiKeShoes->Show();//构造优衣库服装工厂对象ConcreteFactoryuniqloFactory;//创建优衣库衣服对象Clothe*pUniqloClothe=uniqloFactory.CreateProduct();//打印优衣库口号pUniqloClothe->Show();//释放资源deletepNiKeShoes;pNiKeShoes=NULL;删除pUniqloClothe;pUniqloClothe=NULL;doitIamUniqloclothes,myslogan:我是优衣库产品注册模板类+单例工厂模板类虽然新产品前面的模板工厂不需要添加具体的工厂类,但是缺少一个可以统一类随时随地获取指定的产品对象。仍有改进的余地。我们可以将商品注册对象保存在std::map中,通过key-valve的方式,轻松简单的获取对应的商品对象实例。实现总体思路:将商品注册的功能封装成一个商品注册模板类。注册的产品对象保存在工厂模板类的std::map中,方便获取产品对象。将获取产品对象的功能封装到一个工厂模板类中。为了随时随地获取指定的产品对象,工厂设计成单例模式。UML图:商品注册模板类+单例工厂模板类:IProductRegistrar是商品注册的抽象类,模板参数ProductType_t所代表的类是抽象的商品类(如Shoes,Clothes)。提供用于创建产品对象的纯虚函数CreateProduct。ProductFactory是一个工厂模板类,模板参数ProductType_t所代表的类是一个抽象的产品类(如Shoes,Clothes)。用于将注册的商品对象保存到std::map中,并获取对应的商品对象。ProductRegistrar是一个产品注册模板类。模板参数ProductType_t所代表的类是抽象的商品类(如Shoes、Clothe),ProductImpl_t所代表的类是具体的商品(如NikeShoes、UniqloClothe)。用于将产品注册到工厂类并创建产品实例对象。//基类,产品注册模板接口类//模板参数ProductType_t所代表的类为产品抽象类模板classIProductRegistrar{public://获取产品对象抽象接口virtualProductType_t*CreateProduct()=0;protected://禁止外部构造和虚构,子类的其他“内部”函数可以调用IProductRegistrar(){}virtual~IProductRegistrar(){}private://禁止外部复制和赋值操作IProductRegistrar(constIProductRegistrar&);constIProductRegistrar&operator=(constIProductRegistrar&);};//工厂模板类,用于获取和注册产品对象//模板参数ProductType_t表示的类为产品抽象类模板classProductFactory{public://获取工厂订单例如工厂实例是唯一的staticProductFactory&Instance(){staticProductFactoryinstance;返回实例;}//产品注册voidRegistrarProduct(IProductRegistrar*registrar,std::stringname){m_ProductRegistry[name]=registrar;}//根据名称name,获取对应的具体商品对象ProductType_t*GetProduct(std::stringname){//从map中查找已注册的产品,返回产品对象}//未注册产品,错误未找到std::cout<<"Noproductfoundfor"<*>m_ProductRegistry;};//商品注册模板类,用于创建具体商品,注册商品来自工厂//模板参数ProductType_t代表的类是产品抽象类(基类),ProductImpl_t代表的类是具体的产品(产品类型的子类)模板classProductRegistrar:publicIProductRegistrar{public://构造函数,用于将产品注册到工厂,只能调用explicitProductRegistrar(std::stringname){//通过工厂单例将产品注册到工厂ProductFactory::Instance().RegisterProduct(this,name);}//创建一个特定的产品对象指针ProductType_t*CreateProduct(){returnnewProductImpl_t();}};main函数,通过ProductRegistrar注册各种类型的Product,指定的product对象由unity中的ProductFactory单例工厂获取intmain(){//=====================================================================================================================================////注册产品类别作为Shoes(基本类别),产品作为Nike(子类别)到工厂,产品名称为nikeProductRegistrarnikeShoes("nike");//从工厂Shoes*pNiKeShoes=ProductFactory::Instance().GetProduct("nike")中获取产品类型为Shoes、名称为nike的产品对象//显示产品的标语pNiKeShoes->show();//释放资源if(pnikeshoes){deletepnikeshoes;}//===================================================================================================================================================================================,,使用它。Process==============================////注册商品类型为Clothe(基类),商品为UniqloClothe(子类)到工厂,产品名称为uniqloProductRegistraradidasShoes("uniqlo");//从工厂获取产品类型为Shoes、名称为adidas的产品对象Clothe*pUniqloClothe=ProductFactory::Instance().GetProduct("uniqlo");//显示产品的标语pUniqloClothe->Show();//释放资源if(pUniqloClothe){deletepUniqloClothe;}return0;}输出结果:[root@lincodingfactory]#./singleFactory我是耐克运动鞋,我的口号:Justdoit我是优衣库衣服,我的口号:我是优衣库总结将工厂方法模型改进为模板工厂Factory,虽然可以解决添加新产品时添加具体工厂类的问题,但是缺少一种随时随地获取产品对象的方法,说明模板工厂改进为产品注册模板类还有改进空间+一个单例工厂模板类,商品注册模板类用于注册不同类型的商品,单例工厂模板类用于获取指定的注册商品对象。这样就可以很好地将工厂模式下产品注册和获取的主要功能抽象成两个类,利用单例模式可以让工厂类随时随地获取注册的产品对象。因此产品注册模板类+单例工厂模板类的工厂模型达到了开闭规律,具有高扩展性和高封装性。PS:如果想了解更多单例模式,可以参考C++线程安全单例模式总结文章阅读。