首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何用工厂设计模式处理不同长度的建筑工人?

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

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
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
代码运行次数:0
运行
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
代码运行次数:0
运行
AI代码解释
复制
typedef std::function<std::shared_ptr<Pet>(const std::string& name)> PetFactory;

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

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

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

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

Stack Overflow用户

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

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

代码语言:javascript
代码运行次数:0
运行
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

复制
相关文章
jekyll中URL的设置
在配置文件中添加配置类似于 permalink: /:categories/:year-:month-:day-:title.html
码客说
2019/10/22
2.1K0
asp.net 2.0 中GridView里设置日期格式
在asp.net1.0中的datagrid中设置日期字段格式时用DataFormatStr
Java架构师必看
2021/03/22
2.3K0
在推荐系统中,我还有隐私吗?联邦学习:你可以有
随着互联网覆盖范围的扩大,越来越多的用户习惯于在网上消费各种形式的内容,推荐系统应运而生。推荐系统在我们的日常生活中无处不在,它们非常有用,既可以节省时间,又可以帮助我们发现与我们的兴趣相关的东西。目前,推荐系统是消费领域最常见的机器学习算法之一[1]。以网络新闻为例,由于每天都有大量的新闻文章发布在网上,在线新闻服务的用户面临着严重的信息过载。不同的用户通常喜欢不同的新闻信息。因此,个性化新闻推荐技术被广泛应用于用户的个性化新闻展示和服务中。关于新闻的推荐算法 / 模型研究已经引起了学术界和产业界的广泛关注。
机器之心
2020/12/03
4.7K0
在推荐系统中,我还有隐私吗?联邦学习:你可以有
在ASP.NET 2.0中建立站点导航层次
站点导航提供程序--ASP.NET 2.0中的站点导航提供程序暴露了应用程序中的页面的导航信息,它允许你单独地定义站点的结构,而不用考虑页面的实际物理布局。默认的站点导航提供程序是基于XML的,但是你也可以通过编写自定义的提供程序,从任何后端位置暴露这些信息。
Java架构师必看
2021/03/22
7.1K0
在ASP.NET MVC 中获取当前URL、controller、action
一、URL的获取很简单,ASP.NET通用: 【1】获取 完整url (协议名+域名+虚拟目录名+文件名+参数)  string url=Request.Url.ToString();  【2】获取 虚拟目录名+页面名+参数:  string url=Request.RawUrl; (或 string url=Request.Url.PathAndQuery;) 【3】获取 虚拟目录名+页面名: string url=HttpContext.Current.Request.Url.AbsoluteP
欢醉
2018/01/22
2.5K0
用好ASP.NET 2.0的URL映射
URL映射是ASP.NET 2.0中提供的新特性。URL映射技术帮助我们将一个特定URL映射为另一个URL。为了帮助理解,我们假设你在站点有一个叫Homepage.aspx的页面来访问主页,所有的用户也都用这个页面来访问你的主页。但由于某些原因,你要将主页改为OriginalHome.aspx。此时使用URL映射让你可以映射到新页面,而不必通知用户。
Java架构师必看
2021/03/22
8100
ASP.NET 2.0 中的异步页[来自MSDN]
ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等。但我认为最棒的功能是异步页,接下来让我告诉您其中的原因。 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程。一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求。如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用返回),那么分配给该请求的线程在调用返回之前处于挂起状态。这影响了可伸缩性,原因是线程池
菩提树下的杨过
2018/01/23
1.9K0
ASP.NET 2.0 中的异步页[来自MSDN]
ASP.NET 2.0 中 Web 事件
ASP.NET 2.0 还提供了全功能的应用程序监视和健康监视。这个系统是由一个完全可扩展事件模型和一个能将事件发送到多种接收器的事件引擎组成的。举例来说,您可以配置您的 ASP.NET 应用程序来每天发送电子邮件,表明服务器正在运行并且包括可用内存的数量。同样,您可以创建一个链接到未处理异常的健康事件。异常内容、请求标题以及时间和日期都可以被发送到一个错误日志记录数据库。 ASP.NET 2.0 包含了内置的事件,包括心跳、应用程序生存期事件(启动/停止/编译)和错误陷阱事件(未处理异常)。不过,,您可
张善友
2018/01/19
2.2K0
ASP.NET 2.0中GRIDVIEW排序
headertemplate中加一张UP.GIF和DOWN.GIF(就是升序,倒序的示意图)
Java架构师必看
2021/03/22
1K0
在sublime-text 中设置浏览器预览方法(2)
然后通过ctrl + k, ctrl + b打开侧边栏,在侧边栏的文件中右击,找到 open width -> edit applications
李维亮
2021/07/09
6550
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET 2.0的主题和皮肤特性使你能够把样式和布局信息存放到一组独立的文件中,总称为主题(Theme)。接下来我们可以把这个主题应用到任何站点,用于改变该站点内的页面和控件的外观和感觉。通过改变主题的内容,而不用改变站点的单个页面,就可以轻易地改变站点的样式。主题也可以在开发者之间共享。
Java架构师必看
2021/03/22
3.5K0
我应该使用 PyCharm 在 Python 中编程吗?
Python 是一种广泛使用的编程语言,以其简单、多功能和庞大的开发人员社区而闻名。这个社区不断创建新的库和工具,以提高Python编程的效率和便利性。选择正确的环境来编写和调试 Python 代码可能具有挑战性,但 PyCharm 是一个很好的选择,从其他选项中脱颖而出。
很酷的站长
2023/02/20
4.7K0
我应该使用 PyCharm 在 Python 中编程吗?
在HTML网页中巧用URL
首先,先放出一个地址给大家测试 http://cnbruce.com/test/htmlpro/?name=cnbruce&email=cnbruce@126.com 1,时下流行的(可能是吧,因为最
Java架构师必看
2021/03/22
1.7K0
asp.net 2.0中的弹出对话框
在asp.net 1.1中,要做1个弹出的对话框的话,一般是在服务端的代码中这样写:
Java架构师必看
2021/03/22
2K0
如何在 ASP.NET Core 中重写 URL
所谓URL重写指的是更改当前执行的URL,将其指向另外的URL以继续处理当前请求或重定向到外部URL。在ASP.NET中我们可以使用HttpContext.RewritePath方法,但在.NET Core中它并不存在。下面我我们将学习重写和重定向之间的区别,和何时以及如何在ASP.NET Core 中使用它们。 实际开发中,常见的重写URL场景有如下四种:
喵叔
2021/12/05
3.2K0
Asp.Net MVC2.0 Url 路由入门
   本篇文章是初识Asp.Net MVC2.0 的后续的介绍。此文将从Routing未开放源代码开始,还会对Asp.Net的Url重写技术做个简单介绍。并简单介绍Asp.Net MVC2.0 Url路由技术的使用。
老马
2022/05/10
8710
kubernetes中为容器设置内核参数
注意:此方式如果使用了非安全内核参数,必须要先修改节点的kubelet配置,增加--allowed-unsafe-sysctls字段,并允许相关非安全参数,否则创建后,pod会报错SysctlForbidden,并大量不断创建pod,可能将集群搞挂
铜锣烧
2022/12/09
1.8K0
ASP.NET 2.0中Page事件的执行顺序
Page.PreInit Page.Init Page.InitComplite Page.PreLoad Page.Load Page.LoadComplete Page.PreRender Page.PreRenderComplete
Java架构师必看
2021/03/22
7280
在ASP.NET MVC中通过URL路由实现对多语言的支持
对于一个需要支持多语言的Web应用,一个很常见的使用方式就是通过请求地址来控制界面呈现所基于的语言文化,比如我们在表示请求地址的URL中将上语言文化代码(比如en或者en-US)来指导服务器应该采用怎
蒋金楠
2018/01/15
1.7K0
在ASP.NET MVC中通过URL路由实现对多语言的支持
thinkphp3.2.3中设置路由,优化url
需求: 访问这个目录的时候,http://xx.com/p-412313要重定向到(暂且这么叫)http://xx.com/Home/Blog/index/id/412313
全栈程序员站长
2022/07/07
1.2K0
thinkphp3.2.3中设置路由,优化url

相似问题

我可以在ASP.NET 2.0中使用Silverlight 2.0吗?

25

appsettings.json in ASP.net Core2.0预览配置GetSection null

33

DotNetCore2.0中appSettings.json中的SMTP设置

20

在appsettings.json内核中自动为开发和发布环境设置asp.net?

108

点网内核预览-2.0中的身份验证

39
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

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

洞察 腾讯核心技术

剖析业界实践案例

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