当前位置:网站首页>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;
}边栏推荐
- ShardingSphere数据库读写分离
- Kyligence attended the Huawei global smart finance summit to accelerate the expansion of the global market
- How the computer accesses the Internet (IV) LAN and server response
- Use Matplotlib to simulate linear regression
- Extension of ES6 function
- com.mysql.cj.jdbc.exceptions. MySQLTransactionRollbackException: Deadlock found when trying to get lo
- The use and Simulation of character and string library functions in C language
- Reptiles and counter crawls: an endless battle
- Today, I met a 38K from Tencent, which let me see the ceiling of the foundation
- Dry goods | three sub domain name collection tools worth collecting
猜你喜欢

OpenCV 图片旋转

Image information is displayed by browser: data:image/png; Base64, + image content

使用Prometheus+Grafana监控MySQL性能指标

Get the data of Tongcheng (elong) Hotel

NC port forwarding

Shengxin commonly used analysis graphics drawing 02 -- unlock the essence of volcano map!

Definition and storage of adjacency table and adjacency storage of directed graph and undirected graph

Demonstration experiment of scrollbar for adjusting image brightness

Gan Development Series II (pggan, Singan)

C language custom types - Enumeration
随机推荐
Eth POS 2.0 stacking test network pledge process
SV casts and constants
Js实现继承的六种方式
The ability to detect movement in vivo and build a safe and reliable payment level "face brushing" experience
C language to achieve a static version of the address book
Nearly 30 colleges and universities were named and praised by the Ministry of education!
Two dimensional convolution -- use of torch.nn.conv2d
The most powerful programmer on the earth is equipped with a "three piece set". Do you know what it is?
Make good use of these seven tips in code review, and it is easy to establish your opposition alliance
How the computer accesses the Internet (IV) LAN and server response
How to remove the top picture of the bubble skin article details of solo blog
Quickly complete the unit test junit4 setting of intelij idea
NPM install reported -4058 error
1688/阿里巴巴按关键字搜索新品数据 API 使用说明
Can CSC open an account for domestic futures? Is it safe?
Memory allocation and recycling strategy
[spoken English] 01 - Introduction to atom
com.mysql.cj.jdbc.exceptions. MySQLTransactionRollbackException: Deadlock found when trying to get lo
The solution of single chip microcomputer not supporting printf floating point type
Openlayers: point aggregation effect