C++笔记(11)工厂模式
建议直接空降至参考文献,点击链接
简单工厂模式

#include<iostream>
using namespace std;
class BasicCamera {
public:
virtual ~BasicCamera() {};
virtual void OpenCamera() = 0;
}; class Hik :public BasicCamera {
public:
void OpenCamera() {
cout << "打开海康相机" << endl;
}
}; class DaHua :public BasicCamera {
public:
void OpenCamera() {
cout << "打开大华相机" << endl;
}
}; class Factory {
public:
BasicCamera* CreateCamera(string type) {
if (type == "Hik")
return new Hik();
else if (type == "DaHua")
return new DaHua();
else
return NULL; } };
int main() {
Factory fac = Factory();
BasicCamera* camera = fac.CreateCamera("Hik");
camera->OpenCamera();
delete camera;
getchar();
return 0;
}
Tips:
1. 由于工厂模式会返回一个基类指针,指向新生成的derived类对象,对象位于heap,为避免泄露内存和其他资源,要将返回的对象delete掉。如果前面的基类(BasicCamera)没有virtual的析构函数,那么通常发生的是对象的derived部分没有被销毁,产生局部销毁的现象。因此必须要加
virtual ~BasicCamera() {};
2. 基类生成对象不合理,因此在基类中定义了纯虚函数

#include<iostream>
using namespace std; class BasicCamera {
public:
virtual ~BasicCamera() {};
virtual void OpenCamera() = 0;
};
class Hik :public BasicCamera {
public:
void OpenCamera() {
cout << "打开海康相机" << endl;
}
};
class DaHua :public BasicCamera {
public:
void OpenCamera() {
cout << "打开大华相机" << endl;
}
}; class Factory {
public:
virtual ~Factory() {}
virtual BasicCamera* CreateCamera() = 0;
};
class HikFactory :public Factory {
BasicCamera* CreateCamera() { return new Hik(); }
};
class DaHuaFactory :public Factory {
DaHua* CreateCamera() { return new DaHua(); }
}; int main() {
Factory* fac = new HikFactory();
BasicCamera* cam = fac->CreateCamera();
cam->OpenCamera();
delete cam;
delete fac;
getchar();
return 0;
}
在以下情况下可以使用工厂方法模式:
- 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
- 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
抽象工厂模式

#include<iostream>
using namespace std;
class BasicCamera {
public:
virtual ~BasicCamera() {};
virtual void OpenCamera() = 0;
};
class HikCamera :public BasicCamera {
public:
void OpenCamera() {
cout << "打开海康相机" << endl;
}
}; class BasicLen {
public:
virtual ~BasicLen() {};
virtual void InstallLen() = 0;
};
class HikLen :public BasicLen {
void InstallLen() {
cout << "安装了海康镜头" << endl;
}
}; class Factory { public:
virtual ~Factory() {};
virtual BasicCamera* CreateCamera() = 0;
virtual BasicLen* CreateLen() = 0;
};
class HikFactory :public Factory {
BasicCamera* CreateCamera() { return new HikCamera(); }
BasicLen* CreateLen() { return new HikLen(); }
}; int main() {
Factory* fac = new HikFactory();
BasicCamera* cam = fac->CreateCamera();
BasicLen* len = fac->CreateLen();
cam->OpenCamera();
len->InstallLen();
delete len;
delete cam;
delete fac;
getchar();
return 0;
}
优点:
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
- 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
抽象模板工厂

#include<iostream>
using namespace std;
class BasicCamera {
public:
virtual ~BasicCamera() {};
virtual void OpenCamera() = 0;
};
class HikCamera :public BasicCamera {
public:
void OpenCamera() {
cout << "打开海康相机" << endl;
}
};
class DaHuaCamera :public BasicCamera {
public:
void OpenCamera() {
cout << "打开大华相机" << endl;
}
}; class BasicLen {
public:
virtual ~BasicLen() {};
virtual void InstallLen() = 0;
};
class HikLen :public BasicLen {
void InstallLen() {
cout << "安装了海康镜头" << endl;
}
}; template <class AbstractProduct_t>
class AbstractFactory {
public:
virtual ~AbstractFactory() {};
virtual AbstractProduct_t* CreateProduct() = 0;
};
template <class AbstractProduct_t, class ConcreteProduct_t>
class ConcreteFactory :public AbstractFactory< AbstractProduct_t> {
public:
AbstractProduct_t* CreateProduct() { return new ConcreteProduct_t(); }
}; int main() {
AbstractFactory<BasicCamera>* fac = new ConcreteFactory<BasicCamera, HikCamera>();
AbstractFactory<BasicCamera>* fac1 = new ConcreteFactory<BasicCamera, DaHuaCamera>();
AbstractFactory<BasicLen>* fac2 = new ConcreteFactory<BasicLen, HikLen>();
BasicCamera* cam = fac->CreateProduct();
BasicCamera* cam1 = fac1->CreateProduct();
BasicLen* len = fac2->CreateProduct();
cam->OpenCamera();
cam1->OpenCamera();
len->InstallLen();
delete cam,cam1,len,fac,fac1,fac2;
getchar();
return 0;
}
产品注册模板类+单例工厂模板类
#include<iostream>
#include <map>
using namespace std;
class BasicCamera {
public:
virtual ~BasicCamera() {};
virtual void OpenCamera() = 0;
};
class HikCamera :public BasicCamera {
public:
void OpenCamera() {
cout << "打开海康相机" << endl;
}
};
class DaHuaCamera :public BasicCamera {
public:
void OpenCamera() {
cout << "打开大华相机" << endl;
}
}; class BasicLen {
public:
virtual ~BasicLen() {};
virtual void InstallLen() = 0;
};
class HikLen :public BasicLen {
void InstallLen() {
cout << "安装了海康镜头" << endl;
}
}; // 基类,产品注册模板接口类
// 模板参数 ProductType_t 表示的类是产品抽象类
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&);
}; // 工厂模板类,用于获取和注册产品对象
// 模板参数 ProductType_t 表示的类是产品抽象类
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;
} // 根据名字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:产品类型
map<string, IProductRegistrar<ProductType_t>*> m_ProductRegistry;
};
// 产品注册模板类,用于创建具体产品和从工厂里注册产品
// 模板参数 ProductType_t 表示的类是产品抽象类(基类),ProductImpl_t 表示的类是具体产品(产品种类的子类)
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();
}
}; int main() {
IProductRegistrar<BasicCamera>* reg = new ProductRegistrar<BasicCamera, HikCamera>("camera_Hik");
BasicCamera* cam = ProductFactory<BasicCamera>::Instance().GetProduct("camera_Hik");
cam->OpenCamera();
if (cam) delete cam;
getchar();
return 0;
}
产品注册的对象用std::map的方式保存,通过key-valve的方式可以轻松简单的获取对应的产品对象实例。
Tips:(未完成)
1. Instance
单例模式
2. map
map是STL的一个关联容器,它提供一对一的hash
- 第一个可以称为关键字(key),每个关键字只能在map中出现一次;
- 第二个可能称为该关键字的值(value);
参考文献
https://www.cnblogs.com/xiaolincoding/p/11524376.html
https://www.cnblogs.com/xiaolincoding/p/11524401.html
https://www.zhihu.com/question/20367734/answer/1089721250
C++笔记(11)工厂模式的更多相关文章
- Java学习笔记——Java工厂模式之简单工厂
package com.app; import java.util.Date; /* * 工厂模式:简单工厂.工厂方法.抽象工厂 * * */ public class Test0718_Factor ...
- HeadFirst设计模式读书笔记(4)-工厂模式
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类. 所有工厂模式都用来封装对象的创建.工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象 ...
- 学习笔记——抽象工厂模式Abstract Factory
在工厂模式的基础上,通过为工厂类增加接口,实现其他产品的生产,而不用一类产品就增加一个工厂. 依然以<真菌世界>游戏故事类比,树作为工厂,如果现在有两类树,一类生产快速弄真菌飞机和20毫米 ...
- C#学习笔记-抽象工厂模式
题目1:数据访问,通过数据库对用户表单的进行访问,数据库包含SQL Server,对用户表单进行“新增用户”和“查询用户”信息等操作. 分析: 首先,确认用户表单,里面包含两个ID和Name两个字段, ...
- 设计模式之笔记--抽象工厂模式(Abstract Factory)
抽象工厂模式(Abstract Factory) 定义 抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 类图 描述 多个抽象产品 ...
- 设计模式之笔记--简单工厂模式(Simple Factory)
简单工厂模式(Simple Factory) 类图 描述 简单工厂: 一个抽象产品类,可以派生多个具体产品类: 一个具体工厂类: 工厂只能创建一个具体产品. 应用场景 汽车接口 public inte ...
- 设计模式 笔记 抽象工厂模式 Abstract Factory
//---------------------------15/04/09---------------------------- //Abstract Factory 抽象工厂----对象创建型模式 ...
- HeadFirst设计模式读书笔记之工厂模式
1. 简单工厂 1. 你开了一家披萨店,点披萨的方法可能是这样: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals ...
- 《图解设计模式》读书笔记1-1 Iterator模式
目录 迭代器模式的类图 类图的解释 迭代器模式的代码 解释 原因 思想 迭代器模式的类图 类图的解释 名称 说明 Aggregate 集合接口,有提供迭代器的方法 Iterator 迭代器接口,提供迭 ...
- 工厂模式 - Factory
简单工厂模式 SimpleFactory Pattern,将一个具体类的实例化交给一个静态工厂方法来执行. 特点: 增加功能需要修改工厂类,扩展性较差: 参考: 设计模式学习笔记 - 简单工厂模式: ...
随机推荐
- 整理ionic 系列——页面生命周期
前言 这是整理ionic的开篇,ionic 就不多介绍了,开发混合app的. 正文 Event Desc ionViewDidLoad 当页面加载的时候触发,仅在页面创建的时候触发一次,如果被缓存了, ...
- c# countDownEvent类
前言 把异步先总结完吧. countDownEvent 这东西是干什么的呢? 比如说我们比赛跑步,我们需要得出的是第一二三名得出后就可以先统计出来,因为比较重要,后面没有获得获奖名次的可以后续统计出来 ...
- 从零开始写 Docker(十一)---实现 mydocker exec 进入容器内部
本文为从零开始写 Docker 系列第十一篇,实现类似 docker exec 的功能,使得我们能够进入到指定容器内部. 完整代码见:https://github.com/lixd/mydocker ...
- 接口API用例自动转locust测试用例
做接口测试是必要的,写完接口测试用例,再写locust压测脚本,其实差异不大: 写个简单的py,把接口测试脚本转为locust压测脚本,本例只是简单的示范: 原接口校验脚本: 1 # -*- codi ...
- golang开发 深入理解 context
context的历史 context包在Go 1.7版本正式加入Go标准库.在加入之前我们看看Go团队核心成员Sameer Ajmani在2014年发表的一篇关于context介绍博客,地址:http ...
- shell编程实现用户循环输入
如果你想在Shell脚本中实现一个循环判断用户输入是否正确,并根据情况决定是否退出系统,可以使用一个无限循环(如while true)和条件语句来实现. 以下是一个示例代码,用于演示这种情况: #!/ ...
- PTA三次作业
1.前言: 第一次作业难度较大,从无到有的设计,涉及到的主要类有Paper,Question,AnswerPaper,Main,主要题目方向为字符串判断与字符串处理(提取有效信息),判断对错算总分,配 ...
- MAE 自监督算法介绍和基于 EasyCV 的复现
简介:自监督学习(Self-Supervised Learning)能利用大量无标注的数据进行表征学习,然后在特定下游任务上对参数进行微调.通过这样的方式,能够在较少有标注数据上取得优于有监督学习方 ...
- 提示工程(Prompt Engineering)将ChatGPT调教为傲娇猫娘~喵
Prompt Engineering(提示工程)是指通过设计精心构造的提示(prompt)或者输入,来引导大型语言模型生成特定类型的输出.这个技术背后的原理是利用模型对输入的敏感性,通过提供特定格式或 ...
- 为 RabbitMQ 服务器启用 SSL/TLS
为 RabbitMQ 服务器启用 SSL/TLS 目录 为 RabbitMQ 服务器启用 SSL/TLS 为客户端和服务器生成自签名证书 在 RabbitMQ 服务器中启用 TLS/SSL 支持 使用 ...
