为带有条件编译的产品实现工厂模式

2024-02-14

我想以一种允许我在不引入类型依赖的情况下编译代码的方式实现工厂(或其他模式)。

enum CarType
{
 BMW,
 PORSCHE,
 MERC
};

class CarFactory
{
  public:
 static Car* create(CarType type)
 {
  switch(type)
  {
    case BMW : return new BMWCar();
    case PORSCHE : return new PorscheCar();
    default : return new MercCar();
  }
 }
};

当我编译 CarFactory 时,我需要将 BMWCar、PorscheCar 和 MercCar 作为我的编译/链接单元的一部分。

根据我的代码库的设置方式,我们可能只想发布 BMWCar,或者其中两个或全部三个。所以,我无法使create()取决于类型。

我该如何适应工厂模式呢?另外,我想避免执行 ifdefs,因为这只是我的问题的一个示例。真正的代码库是巨大的,并不是 ifdef 代码的实用解决方案。

更新: 另外,我不允许使用:

  • 模板
  • 必须符合 c++ 98 标准
  • 无法使用升压

这些主要是由于客户构建工具链的限制。我没有选择改变这些。


我通常会做类似的事情:

class CarFactory
{
public:
     static void RegisterCar(CarType t, std::function<Car*()> f)
     {
          getMap().emplace(t, f);
     }
     static Car* create(CarType type)
     {
          return getMap().at(type)();
     }
private:
     static std::unorderd_map<CarType, std::function<Car*()> >& getMap()
     {
         static std::unorderd_map<CarType, std::function<Car*()> > m;
         return m;
     }
};

并在每个类的实现中:

 class BMWCar : public Car
 { 
     struct Init
     {
         Init() 
         {
             CarFactory::RegisterCar(BMW, [](){return new BMWCar(); });
         }
     };
     static Init initializeBmwCar;
     /** .. */ 
 };

 /*** BMWCar.cpp ***/
 BMWCar::Init BMWCar::initializeBmwCar;

这是可行的,因为每种类型在静态初始化期间使用以下方法初始化自己的工厂:static Init object.

这段代码中的巨大痛苦是为了避免初始化顺序失败:一个简单的实现将简单地使用静态映射CarFactory。不幸的是,不能保证BMWCar::initializeBmwCar构造函数将运行after地图在CarFactory。有时某些编译器可能会工作,有时可能会崩溃。 所以想法是使用静态函数(getMap)与静态变量(m),保证第一次初始化getMap叫做。

我知道clang/llvm使用此模式来注册优化过程。

另一种更复杂但更灵活的解决方案是设计一个插件系统,其中每个 DLL 都实现一个car输入并导出一个CreateCar功能。

然后你就可以收集所有这些CreateCar在初始化期间通过动态加载库并调用GetProcAddress/dlsym.

这两种解决方案在 Windows 上实现起来都可能很棘手,因为(除非Car是抽象的)基础Car实现需要进入其自己的库,并且每个插件 dll 都需要与该库链接。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为带有条件编译的产品实现工厂模式 的相关文章

  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 为什么 std::allocator 在 C++17 中丢失成员类型/函数?

    一边看着std 分配器 http en cppreference com w cpp memory allocator 我看到成员 value type pointer const pointer reference const refer
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • 组合框项目为空但数据源已满

    将列表绑定到组合框后 其 dataSource Count 为 5 但组合框项目计数为 0 怎么会这样 我习惯了 Web 编程 而且这是在 Windows 窗体中进行的 所以不行combo DataBind 方法存在 这里的问题是 我试图以
  • C# 创建数组的数组

    我正在尝试创建一个将使用重复数据的数组数组 如下所示 int list1 new int 4 1 2 3 4 int list2 new int 4 5 6 7 8 int list3 new int 4 1 3 2 1 int list4
  • C# 编译器如何决定发出可重定向的程序集引用?

    NET Compact Framework 引入了可重定向程序集引用 现在用于支持可移植类库 基本上 编译器会发出以下 MSIL assembly extern retargetable mscorlib publickeytoken 7C
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • C# 搜索目录中包含字符串的所有文件,然后返回该字符串

    使用用户在文本框中输入的内容 我想搜索目录中的哪个文件包含该文本 然后我想解析出信息 但我似乎找不到该字符串或至少返回信息 任何帮助将不胜感激 我当前的代码 private void btnSearchSerial Click object
  • Silverlight Datagrid:在对列进行排序时突出显示整个列

    我的 Silverlight 应用程序中有一个 DataGrid 我想在对该列进行排序时突出显示整个列 它在概念上与上一个问题类似 Silverlight DataGrid 突出显示整列 https stackoverflow com qu
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS

随机推荐

  • 如何在插件架构中做到免注册COM

    我们使用清单文件来实现免注册 COM 正如我在这另一个问题 https stackoverflow com questions 465882 generate manifest files for registration free com
  • 在哪里添加 String 原型

    我目前正在 Titanium Studio 中使用 JavaScript CommonJS 并且有一个关于原型设计的问题 假设我想向现有的类添加一个新函数 例如 String prototype trim function return t
  • 运行应用程序中的 Grails 3.0 静态 html

    之前曾就 grails 2 3 4 提出过类似的问题 我觉得很奇怪 我找不到一种方法来做到这一点 因为这对我来说似乎是一个标准用例 我只是想在运行 grails run app 时提供 html 页面 包括它们链接的 css 和 js An
  • 使用 asyncio 并行化生成器

    我的应用程序从慢速 I O 源读取数据 进行一些处理 然后将其写入本地文件 我已经用生成器实现了这个 如下所示 import time def io task x print requesting data for input s x ti
  • 您能否返回适用于任何可能的错误类型的结果?

    我想使用多个库 每个库都有自己的错误类型 我并不真正关心每个特定板条箱的错误类型 我想使用 习惯用法是使用那些返回 a 的 crate 的方法Result type 我也不想解开这些值 如果遇到错误 这会导致恐慌 我可能只是想使用传播不同的
  • 光滑的旋转木马 - 强制幻灯片具有相同的高度

    我在使用 Slick carousel JS 插件时遇到了多个问题幻灯片显示它们具有不同的高度 我需要幻灯片相同高度 但是对于 CSS flex box 它不起作用 因为幻灯片具有冲突的 CSS 定义 另外 我在论坛和网络上没有找到任何有用
  • 单例类与具有静态成员的类

    尽管关于该主题的主题有很多 但我仍然不清楚何时选择哪种方法 我希望通过讨论一个具体的例子 我最终能 明白 注意 我这里的语言是 Cocoa 尽管一般问题不是特定于语言的 我有一个类 TaskQueue 我想用它来 从我的代码中的任何位置访问
  • 在 Java 8 中使用两个具有相同签名的默认方法实现两个接口

    假设我有两个接口 public interface I1 default String getGreeting return Good Morning public interface I2 default String getGreeti
  • 如何将 jPCT 与 Vuforia SDK 结合使用?

    有人可以概述一下混合 Jpct 和 Qualcomm Vuforia SDK 的情况吗 将 Java 渲染引擎与 Vuforia 结合使用是个好主意吗 基本上 QCAR 的全部工作就是计算变形的预定义目标图像的变换矩阵 它为您提供了两个重要
  • 新的 Angular2 路由器配置

    回到使用已弃用的路由器时 我能够执行 router config 并传入一个对象 事实是 路由器本身在应用程序启动后进行了一些配置 该对象具有相同的 模板 就像我使用了 RouterConfig 一样 我正在寻找的是是否有一种方法可以像这样
  • POST 403 Forbidden for Chrome 扩展(后端为 Django)

    我以前从未开发过 Chrome 扩展程序 目前正在为我的 Django 应用程序开发 Chrome 扩展程序 具有链接提交功能 当我尝试使用扩展程序提交链接时 出现以下错误 POST http 127 0 0 1 8000 add link
  • 找到未使用的 Javascript 函数?

    我的应用程序中有大约 100 个 js 文件 我需要从这些文件中找到未使用的函数 哪个编辑器或工具可以帮助我 看看JSLint http jslint com help html代码质量工具
  • 如何在 Windows Phone 中对 LongListSelector 进行排序

    我希望能够按升序或降序对绑定到 LongListSelector 的数据进行排序 我无法将排序后的数据绑定到我的 LongListSelector 最初 我的解决方案没有尝试实现排序 而是有效的 但我相信在涉及排序时我遗漏了一些东西 我也尝
  • Google Play Android .apk 上传“无法运行 aapt dump badging”

    自从我上次将应用程序上传到 Google Play 开发者控制台以来已经快一年了 这是我已经签名并压缩对齐的 Cordova 应用程序 按照我过去成功使用的相同流程 我现在收到以下错误 上传失败 无法使用 aapt dump badging
  • 使用 POST 在 R 中抓取动态表

    我正在努力刮这张桌子 http myfwc com wildlifehabitats managed alligator harvest data export 使用 R 到目前为止 我使用下面的代码只得到了 27 行 我想取回所有条目 并
  • 在 iOS 上通过 上传存储在云服务上的文件 0 字节

    我无法弄清楚为什么某些从 iOS 上传到我们服务器的内容会导致空文件 上传页面是一个简单的表单 使用 POST 和 enctype 作为 multipart form data 该问题似乎仅在用户执行以下操作时才会出现 正在使用 iOS 尝
  • 已分析与未分析:存储大小

    我最近开始使用 ElasticSearch 2 据我了解analyzed vs 未分析在映射中 not analyzed 在存储中应该更好 https www elastic co blog elasticsearch storage th
  • 在Android上加载依赖的共享库

    我正在移植大量本机代码和几个相互依赖的库 加载代码失败 因为 Android 链接器仅查找依赖项 system lib 并且不在应用程序安装目录中 data data com packagename nnn lib 作为第一个解决方法 我使
  • Chrome 显示 Lottie 动画模糊

    我遇到了缩放 Lottie 动画的问题 Chrome 模糊了动画 当动画缩放时 这一点尤其明显 在我的示例中 原始动画的尺寸为 842x596px 渲染效果越小 效果越差 如果您想在 Chrome 浏览器中重现它 这里是示例代码 lotti
  • 为带有条件编译的产品实现工厂模式

    我想以一种允许我在不引入类型依赖的情况下编译代码的方式实现工厂 或其他模式 enum CarType BMW PORSCHE MERC class CarFactory public static Car create CarType ty