Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何用工厂设计模式处理不同长度的建筑工人?

如何用工厂设计模式处理不同长度的建筑工人?
EN

Stack Overflow用户
提问于 2015-07-17 06:08:38
回答 5查看 764关注 0票数 5

我希望有一个类,它根据我传递的字符串创建不同类型的对象。根据我的研究,这最好地描述了工厂的设计模式。我正在成功地实现它,但我遇到了一个设计问题:我不知道如何创建具有不同长度构造函数的对象。

让我们举个例子,一个名为Pet的抽象父类。其中有三个孩子:鱼、猫和狗。他们都继承了宠物的重量和颜色,所以他们的建设者也是如此。但是一条鱼可能需要一些鳍和布尔值来判断它是否是咸水鱼。这是一个4参数构造函数。猫想要多少条腿。这是三个参数。这只狗可能有腿的参数,繁殖参数,以及它是否和其他狗一起玩得很好,有5个参数。

在C++中,我理解没有任何反射,所以最常见的做法似乎是将字符串映射声明为函数指针,其中函数指针指向如下所示的函数:

代码语言:javascript
运行
AI代码解释
复制
    template<typename T> Pet* createObject(int weight, std::string color) {return new T(weight, color);}

同样,我不确定如何在不影响其他对象的构造函数调用的情况下将更多的参数插入到调用中。

我可以想出两个解决办法:创建新函数来接受不同数量的参数,或者为超过一定大小的构造函数设置默认参数。

根据我有多少不同的参数大小,解决方案1似乎有点过分。

工作方法2似乎忽略了构造函数的全部要点,因为在调用构造函数之后,我将被迫分配数据。

还有其他更好的解决办法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-07-17 06:38:58

您可以使用各种模板和完美的转发。

代码语言:javascript
运行
AI代码解释
复制
template<typename T, typename... Args>
Pet* createObject(Args&&... args) {
    return new T(std::forward<Args>(args)...);
}

但是,由于任何指针都可以转换为它的基类,如果这个函数返回T*,可能会更好。此外,使用裸指针是不明智的,因为您必须手动删除它们。最好使用shared_ptrunique_ptr。对于这些类,已经有类似的工厂方法:make_sharedmake_unique (后者仅在C++14中)。或者,如果编译器不支持C++11,则可以使用助推中的shared_ptrmake_shared

当然,当您知道编译时需要创建什么样的类型时,此解决方案就可以工作。如果您必须在运行时决定它,那么整个问题必须从一个不同的方向来考虑,就好像您不知道要创建哪种类型一样,那么您就无法知道给出哪些参数,除非所有类型的参数都是通用的。在这种情况下,您需要的是一个抽象工厂模式。幸运的是,C++ (至少来自C++11)提供了一种在不创建大量类的情况下实现此模式的方法。例如,假设您必须创建从Pet派生的某个类的实例。宠物的实际种类、大小和其他属性是在其他地方决定的,而宠物的名称是在创建时决定的。那么,你需要一个这样的工厂:

代码语言:javascript
运行
AI代码解释
复制
typedef std::function<std::shared_ptr<Pet>(const std::string& name)> PetFactory;

在某种程度上,您决定要创建一个Dog (我将实际创建参数的意义留给您的想象)。

代码语言:javascript
运行
AI代码解释
复制
PetFactory petFactory =
        [](const std::string& name) {
            return std::make_shared<Dog>(name, 12, "brown", 23.5);
        }

当您真正创建它时,您只需要调用工厂:

代码语言:javascript
运行
AI代码解释
复制
std::shared_ptr<Pet> pet = petFactory("Pet Name");
票数 3
EN

Stack Overflow用户

发布于 2015-07-17 06:32:11

这就是你所需要的吗(原谅内存泄漏之类的)

代码语言:javascript
运行
AI代码解释
复制
#include <map>
#include <string>

// definition of pet hierarcy
class pet_t
{
public:
    virtual ~pet_t(void) {}
};

class frog_t : public pet_t
{
public:
    frog_t(int) {}
    static frog_t *builder(int n) { return new frog_t(n); }
};

class dog_t : public pet_t
{
public:
    dog_t(const char *, int) {}
    static dog_t *builder(const char *n, int p) { return new dog_t(n, p); }
};
// the per builder function type
typedef pet_t *(*pet_builder_t)(...);
// the map containing per builders: it's indexed by per type name
std::map<std::string, pet_builder_t> registry;
void build_factory(void)
{
    registry["frog"] = reinterpret_cast<pet_builder_t>(&frog_t::builder);
    registry["dog"] = reinterpret_cast<pet_builder_t>(&dog_t::builder);
}
// the actual factory function
template <class ...Ts>
pet_t *factory(std::string name, Ts&&...ts)
{
    pet_builder_t builder = registry[name];
    // assume there is something in the map
    return builder(std::forward<Ts>(ts)...);
}

int main(int argc, char *argv[])
{
    build_factory();
    dog_t  *dog  = dynamic_cast<dog_t  *>(factory(std::string("dog"), std::string("pluto"), 3));
    frog_t *frog = dynamic_cast<frog_t *>(factory(std::string("frog"), 7));
}

我觉得有太多的演员,但这个想法应该是一个很好的起点。

票数 0
EN

Stack Overflow用户

发布于 2015-07-17 06:48:23

如果您创建一个对象时,您已经知道了它的参数,并且它将是一个鱼,那么您根本不需要一个工厂:只需构造一个Fish,您就完成了。

您可以合理地利用一个工厂,以防您不知道调用方会从中产生哪个对象。例如,将字符串作为工厂方法的输入,可能从文件中读取:工厂通过解析字符串创建并返回正确的对象类型。

调用者不知道它是鱼还是狗:这是工厂方法的目标。

此外,当您可以通过继承添加更多“可构造”对象并重写虚拟创建主义方法来扩展工厂时,您还可以利用它。如果方法有不同的签名--它们实际上是不同的方法,则不会发生这种情况。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31477785

复制
相关文章
工作角色与家庭角色冲突
2020 年的工作正式开启,大多数开发者的开工方式是云办公。对开发者来说,云办公意味着什么?如何开始云办公?云办公的发展趋势会怎样?基于此,云加社区联手知乎科技,从知乎云办公相关话题中精选内容落地社区专题「 开发者云办公模式洞察 」。
腾讯云开发者社区
2020/03/20
1.3K0
Rails里应用Devise
Use Devise For Authentication Devise is great gem for authentication, check out here. Add Gem First thing you need to do is to add devise gem to you Gemfile. Just add gem 'devise', '~> 3.5' to your Gemfile and run bundle install and restart your server. Se
用户2183996
2018/06/28
3500
MySQL管理——激活角色
MySQL8.0提供了角色功能,用户需要在激活角色后才能够使用角色赋予的权限。角色可以在服务器、用户和会话三个级别进行激活。用户仅能激活已被授予的角色
MySQLSE
2023/08/31
5240
MySQL管理——激活角色
OpenShift-角色管理
集群级别Role(Cluster Role) admin:可管理除了项目quota外其它所有项目包括的资源对象。 basic-user:可以获得项目和用户的基本信息。 cluster-admin:可以对任何项目进行任何操作。 cluster-status:可以获得集群状态信息的角色。 edit:除了Role和Binding外,可以修改项目中其它对象。 self-provisioner:可以创建属于自己的项目。 view:不能对项目中的对象进行任何更改,但是可以查看项目中的对象 oc get c
heidsoft
2021/08/26
7650
OpenShift-角色管理
为什么游戏角色没有胡子?
点击标题下「大数据文摘」可快捷关注 福布斯中文网授权转载 本文作者JV Chamary是生物学家和作家。 译 于波 校 李其奇 摘自:福布斯中文网(微信公号: forbeschinaonline) 很多角色扮演游戏都允许玩家定制游戏人物的面部特征,由《光晕》(Halo)这款游戏的创造者开发的新款“共享世界射击游戏”也不例外。 在选择种族(人类、觉醒者或Exo机械族)后,你可以调整包括脸型、发型、眼睛颜色和肤色在内的所有面部特征,创造出独一无二的游戏人物。只不过缺少了一样东西:胡子。 从《命运》的Beta测试
大数据文摘
2018/05/22
9880
【学生管理系统】权限管理之角色管理
   @PostMapping("/addPerm")    public BaseResult addPermWithRoleId(@RequestBody SysRole sysRole) {        try {            // 添加权限            sysRolePermissionService.addPermWithRoleId(sysRole); ​            // 提示            return BaseResult.ok("授权成功");       } catch (Exception e) {            return BaseResult.error("授权失败");       } ​   }
陶然同学
2023/02/24
1.9K0
【学生管理系统】权限管理之角色管理
MySQL8.0 角色管理
官方文档的第一句话,就开门见山的告诉了我们角色是什么东西。A MySQL role is a named collection of privileges. Like user accounts, roles can have privileges granted to and revoked from them.
AsiaYe
2021/11/25
1.6K0
造轮子之角色管理
在asp.net core identity中已经有RoleManager,我们只需要封装一下API操作Role即可完成我们角色管理相关功能,这里API打算只提供分页查询,创建以及删除,不提供修改API。
饭勺oO
2023/10/18
1610
Oracle 用户、角色管理简介
3)DEFAULT TABLESPACE testtbs001:指定在用户方案(schema)中创建的对象的默认表空间为testtbs001
授客
2019/09/11
1.2K0
Grafana -- 用户角色管理(三)
在日常 Grafana 使用中需要针对不同用户开放不同的 dashboard 权限,根据不同角色进行权限管理。Grafana 角色大致分为以下三类:
Kevin song
2020/11/06
5.6K0
那些数据工作中的角色
数据工作中有一类非常重要的角色,那就是数据分析师。为什么这个角色这么重要呢?因为要是没有这个角色,不管一个企业中的数据管理做得有多么好都没用,都无法带来实际的价值。这些数据就像是藏在海底的石油,而数据分析师就是开采海底石油的油井设备。要想让石油用于汽车轮船,需要通过这些设备先将海底的石油抽取出来,经过加工处理,提纯。
ThoughtWorks
2021/07/02
4780
PostgreSQL用户角色和权限管理
4、任何属于该组角色的对象都必须先被删除或者将对象的所有者赋予其它角色,任何赋予该组角色的权限也都必须被撤消。
数据和云
2022/02/25
4.8K0
PostgreSQL用户角色和权限管理
MySQL 8.0用户和角色管理
MySQL8.0新加了很多功能,其中在用户管理中增加了角色的管理,默认的密码加密方式也做了调整,由之前的sha1改为了sha2,同时加上5.7的禁用用户和用户过期的设置,这样方面用户的管理和权限的管理,也增加了用户的安全性。
田帅萌
2018/08/14
2.9K0
MySQL 8.0用户和角色管理
SQLServer 服务器角色管理
常用的为:db_datareader(查权限)db_datawriter(增删改权限)db_owner(完全权限)
李郑
2019/12/04
3.1K0
基于Python-Flask的权限管理:角色管理
一、前言 角色管理主要管理角色信息,不同的角色可以访问不同的菜单和数据。 image 二、后端实现 1.ORM类 from db import db from models.BaseModel imp
Python之道
2020/06/02
4K1
基于Python-Flask的权限管理:角色管理
POJ 1936 All in All
You have devised a new encryption technique which encodes a message by inserting between its characters randomly generated strings in a clever way. Because of pending patent issues we will not discuss in detail how the strings are generated and inserted into the original message. To validate your method, however, it is necessary to write a program that checks if the message is really encoded in the final string.
谙忆
2021/01/19
3920
​MySQL8.0角色管理---(三)
类似将角色授予账户一样,我们可以使用revoke的方法从账户中撤销角色,下面我们演示从账号yeyz_ro中撤销角色role_ro角色:
AsiaYe
2020/02/25
7030
MongoDB运维与开发(五)---角色管理
之前的两篇文章,我们已经讲清楚了MongoDB的用户权限管理,接下来的文章我们来看MongoDB的角色管理。
AsiaYe
2020/11/10
9010
MongoDB运维与开发(五)---角色管理
MySQL8.0角色管理---(一)
今天看了看MySQL8.0官方文档的角色管理部分,写点东西总结下这块的内容吧。
AsiaYe
2020/02/25
5870
技术转管理(一):角色的转变认知
祝大家国庆假期节日快乐哈。因厦门疫情比较严重,今年国庆就乖乖的宅家里啦,今天和大家聊一聊程序员如何转型做管理。
用户7533190
2022/09/22
8550
技术转管理(一):角色的转变认知

相似问题

Cakephp 403错误不显示自定义页面

12

根据标题类型显示内容

11

自定义错误页面内容未正确显示

20

根据索引页面上的内容类型自定义节点的内容块

20

显示内容自定义页面

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文