当前位置:网站首页>new也可以创建对象,为什么需要工厂模式?
new也可以创建对象,为什么需要工厂模式?
2022-07-24 17:42:00 【用户6557940】
设计模式里,工厂模式是一类创建型的设计模式。为遵循软件设计和开发的开闭原则,先后衍生出了简单工厂模式,工厂方法模式和抽象工厂模式。作为一种创建型的设计模式,工厂模式是用来创建新对象的。那么问题就来了,以C++为例,C++的类明明构造函数也可以创建新的对象啊,为什么非得引入工厂模式呢?
封装创建对象时的初始化工作
如果使用C语言,分配并初始化的工作包括:
- malloc申请内存(但申请完了对象并没有初始化,只是有了一片内存空间),并强制类型转换
- 初始化这块内存
- Do other works
好像有点麻烦,分配内存、类型转换、初始化。如果是C++,new的动作包括分配内存和调用构造函数两个步骤,比较简化了。这是对一般的初始化过程比较简单的对象。那如果初始化过程比较复杂呢?什么叫比较复杂的初始化过程呢?就是说创建对象不仅是分配内存空间,还要做一些其他初始化工作,甚至是与外部变量或者资源相关的工作。
下面的代码是NVDLA的compiler的源码中的一部分:
SDPScaleOpNode* NodeFactory::newSDPScaleOpNode
(
ScaleNode* origCanNode,
Graph* engGraph
)
{
B b;
DD dd;
NvU16 numBatches = engGraph->profile()->multiBatchSize();
b = dd = new SDPScaleOpNode(origCanNode, numBatches);
dd->setName(std::string("sdp-scale-") + toString(s_sdp_scale_priv.size()));
dd->setId(engGraph->nextNodeId());
dd->setGraph(engGraph);
engGraph->insertNode(b);
s_sdp_scale_priv.insert(std::pair<B, DD>(b, dd));
return dd;
}我删去了部分代码以便于观察。该接口是要创建一个SDPScaleOpNode,但封装在NodeFactory的newSDPScaleOpNode()接口里。该接口里除了
new SDPScaleOpNode(origCanNode, numBatches);以外,还有其他setter和insert工作。如果不用工厂模式封装,则每创建一个node,都要在创建node的地方写上其他setter和insert的代码,不便于阅读,而且造成代码冗余。
下面代码是tensorflow源码中的一个片段。可以看到,创建device的初始化过程更加复杂,甚至还可以处理一些异常。
std::unique_ptr<Device> DeviceFactory::NewDevice(const string& type,
const SessionOptions& options,
const string& name_prefix) {
auto device_factory = GetFactory(type);
if (!device_factory) {
return nullptr;
}
SessionOptions opt = options;
(*opt.config.mutable_device_count())[type] = 1;
std::vector<std::unique_ptr<Device>> devices;
TF_CHECK_OK(device_factory->CreateDevices(opt, name_prefix, &devices));
int expected_num_devices = 1;
auto iter = options.config.device_count().find(type);
if (iter != options.config.device_count().end()) {
expected_num_devices = iter->second;
}
DCHECK_EQ(devices.size(), static_cast<size_t>(expected_num_devices));
return std::move(devices[0]);
}统一创建对象的接口命名
有了上面的例子,也就比较好理解“统一接口命名”了。
- 如果是class Football,那么创建是要new Football;
- 如果创建Basketball,则要new Basketball;
- 如果是Volleyball,则new VolleyBall;
- 如果是AbcdEfgHijkOpq1234567,则new AbcdEfgHijkOpq1234567(类的名字很长)。
如果有工厂模式做封装,那么就成了
createFootball();
createBasketball();
createVolleyball();
createAbcdEfgHijkOpq1234567();接口命名很清晰,并且能够通过函数名大概知道它的作用。
对象是否真的需要“创建”?
每次new,都会去分配内存(不谈placement new)。但是有的场景下,我们真的需要每次都分配内存吗?要从线程池里获取一个线程,要从内存池里获取一片内存,要从某个资源池里获取一个资源,这些资源本身就有,不需要重新分配,除非池里的资源也用完了。所以工厂模式的另一个作用是,掌控某些资源分配的时机,当真正需要分配内存的时候,才去分配。
结合多态,便于扩展
工厂模式结合多态,定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化,增加代码的灵活性。比如下列代码,通过一个统一的接口getSportProduct(),运行时可创建出不同的产品。
int test()
{
AbstractFactory *fac = NULL;
AbstractSportProduct *product = NULL;
fac = new BasketballFactory();
product = fac->getSportProduct();
fac = new FootballFactory();
product = fac->getSportProduct();
fac = new VolleyballFactory();
product = fac->getSportProduct();
// other work
return 0;
}边栏推荐
- Niuke linked list solution record
- 2022 牛客暑期多校 K - Link with Bracket Sequence I(线性dp)
- Scept: consistent and strategy based trajectory prediction for planned scenarios
- Ipaylinks, a cross-border payment integration service, won the 3A Asia Award of treasury
- C language custom type explanation - structure
- ROC and AUC details of the recommended system
- 阿里巴巴/166获得店铺的所有商品 API使用说明
- Can CSC open an account for domestic futures? Is it safe?
- 邻接表的定义和存储以及有向图无向图的邻接存储
- Array double pointer - deliberate practice
猜你喜欢

Iqiyi Tiktok reconciled, Weibo lying gun?

C语言实现静态版本的通讯录

Common questions of testers during interview

C语言自定义类型讲解 — 联合体

Huawei machine test - topic core test point

Number theory division block explanation example: 2021 Shaanxi Race C

ROC and AUC details of the recommended system

Tensorflow introductory tutorial (40) -- acunet

干货|值得收藏的三款子域名收集工具

MySQL数据库的一个问题
随机推荐
Shardingsphere database read / write separation
How to remove the top picture of the bubble skin article details of solo blog
C language programming training topics: K characters in left-handed string, little Lele and Euclidean, printing arrow pattern, civil servant interview, poplar matrix
es(1)
Use yarn
Definition and storage of adjacency table and adjacency storage of directed graph and undirected graph
Still using xshell? You are out, recommend a more modern terminal connection tool!
[spoken English] 01 - Introduction to atom
Supervisor common commands
A problem of MySQL database
快速完成intelij idea的单元测试JUnit4设置
Eth POS 2.0 stacking test network pledge process
Introduction and use of Pinia
JS image conversion Base64 Base64 conversion to file object
Atcoder beginer 202 e - count descendants (heuristic merge on heavy chain split tree for offline query)
Class bytecode file
使用Prometheus+Grafana监控MySQL性能指标
C language custom type explanation - structure
213. 打家劫舍 II-动态规划
NC port forwarding