实现抽象工厂模式的最佳方法

2023-12-10

考虑以下代码:

#include <stdio.h>


// =============================


class Shape{
public:
    virtual ~Shape(){};

    virtual void process() = 0;
};

class Triangle : public Shape{
public:
    virtual void process() override {
        printf("BBB\n");
    }
};


// =============================


/* option 1 */
class TriangleProducer{
public:
    Triangle factory(){
        return Triangle {};
    }
};



/* option 2 */
class PtrShapeProducer{
public:
    Shape *factory(){
        return new Triangle {};
    }
};



/* option 3 */
class PimplShape : public Shape{
    Shape *sh;
public:
    PimplShape(Shape *sh) : sh(sh){
    }

    virtual ~PimplShape() override{
        delete sh;
    }

    virtual void process() override {
        sh->process();
    }
};

class PimplShapeProducer{
public:

    PimplShape factory(){
        return new Triangle {};
    }
};


// =============================


int main(){
    TriangleProducer f1;
    Triangle tri = f1.factory();
    tri.process();



    PtrShapeProducer f2;
    Shape & sh = *f2.factory();
    sh.process();
    delete & sh;



    PtrShapeProducer f3;
    PimplShape psh = f3.factory();
    psh.process();



    return 0;
}

OPTION 1

不错,但是并没有真正实现多态。返回类型是已知的,您必须匹配它。可以加一个auto代替Triangle,但这除了更容易重构之外不会改变任何东西。

OPTION 2

Java 和 PHP 就是这样做的。但我知道“原始”指针在 C++ 中是不可取的。可以加一个std::unique_ptr,但这并没有改变任何东西,除了缺失delete陈述。

OPTION 3

这是前段时间有人在这里提出的建议 - 效果很好,没有“原始”指针,没有删除。但代码太多,而且太复杂——看起来很奇特,但不是正确的方法。

OPTION 4(此处未实现)

使用 const 引用 - 然而它们是 const 并且它不会改变“工厂”返回类型。我认为,这更像是变异,而不是真实的选择。

我还缺少其他选择吗?
另外,最好的选择是什么?


我认为最惯用语现代 C++ 方法是您顺便提到但忽略的方法。返回一个std::unique_ptr<Shape>.

它是安全的,清楚地表达所有权,支持多态性并且不需要太多代码。

class ShapeFactory {
public:
  std::unique_ptr<Shape> create(){
    return std::make_unique<Triangle>();
  }
};

但我不想声称这是“最好”的方法。

Your PimplShape选项3实际上与a非常相似unique_ptr只是不太通用或经过测试。

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

实现抽象工厂模式的最佳方法 的相关文章

随机推荐

  • 使用 xyz 坐标和 jzy3d 构建 3D 曲面图

    我一直在寻找一种将 coord x y z 列表发送到 jzy3d 的方法 但没有成功 我发现的唯一方法是使用带有 coord3d 列表和 镶嵌器 列表的 构建器 但它实际上不起作用 事实上我真的不明白 Tessellator 的含义 这是
  • 按自定义订单排序

    我想知道如何按自定义顺序而不是按字母顺序对数组进行排序 想象一下你有这个数组 对象 var somethingToSort type fruit name banana type candy name twix type vegetable
  • 管理 @NamedNativeQuery 和架构

    我有很多EntityManager 我拥有的每个模式一个 我使用entity mappings文件来映射 EM 与模式 有用 当我使用 NamedQuery它的工作就像一个魅力 但当我使用 NamedNativeQuery不使用架构 我必须
  • 如何更改 Firebird 上的 CHECK 约束?

    我有一个像这样的 Firebird 表 CREATE TABLE events event VARCHAR 6 NOT NULL CHECK event IN deploy revert fail change id CHAR 40 NOT
  • 使用 pytables 或 pandas 删除表或节点后释放 hdf5 磁盘内存

    我将 HDFStore 与 pandas pytables 一起使用 删除表或对象后 hdf5 文件大小不受影响 当添加额外的对象来存储时 这个空间似乎会被重用 但如果浪费大量空间 这可能会成为一个问题 我在 pandas 或 pytabl
  • 使用 Jquery 停止 Vimeo 视频

    我需要停止嵌入了新的 oembed api 通用播放器 的 Vimeo 视频 但是当我尝试添加事件时出现此错误 Uncaught TypeError Object
  • CSS:修复可变高度元素内部分的高度

    相关这个问题 这是一个小提琴 http jsfiddle net DRbRS 请注意 红色轮廓列表 div 未与绿色容器 div 的底部对齐 问题在于 即使标题的高度已知 也无法提前知道列表的最终高度应该是多少 有什么办法可以在不诉诸jav
  • ES6 模块导入给出“Uncaught SyntaxError:意外标识符”

    对于个人项目 我尝试使用 ES6 import 来编写更清晰的代码 作为第一个测试 我正在编写一个应该生成菜单的对象 当我直接加载类时 整个代码都可以工作 但是当在 ES6 中使用导入和导出时 它会在import线路输入main js 我有
  • 使用 IdentityServer4 身份验证为 ClaimsIdentity 设置自定义声明

    我有一个使用 IdentityServer4 TokenValidation 进行身份验证的 ASP NET Core 2 1 应用程序 authenticationBuilder AddIdentityServerAuthenticati
  • 使用文字创建 Javascript 对象与自定义构造函数

    我知道有多种方法可以在 javascript 中创建对象 并且我一直在阅读对象文字语法通常是首选 正确的 我无法弄清楚是否有理由使用任何其他方法来创建对象 例如自定义构造函数 var p new Person Adam 仅当我想要私有变量或
  • 如何在没有 :nth 伪类的情况下选择元素的前两个子元素?

    我目前正在为高中生网络开发区域锦标赛做准备 准备任务是锦标赛网站要解决的任务之一 我有以下 HTML 代码 h2 Task 5 h2
  • 使用带有访问“连续表单”的未绑定组合框进行钻取

    必须有一种简单的方法来做到这一点 我遇到一种情况 我使用连续形式列出零件 零件清单包含零件类型 制造商 零件编号和数量等信息 该列表包含零件实例和数量 我可以从部件的实例中查找其他内容 因此显示现有部件没有问题 只需使用联接查询来检索相关记
  • LINQ for Java 工具[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 LINQ for java
  • Android - 获取折线作为图像

    如何获取已在 Google 地图上绘制为图像的折线 只有折线 没有地图布局 我已经在 Google 地图上绘制了折线 我想将折线作为图像获取 所以只显示红线 没有任何地图 https i stack imgur com vUqS3 png
  • xpath:选择父级和过滤子级

    给定一个 xml 块
  • 在表单中设置默认值

    我想在我的表单中设置一个默认值 我正在这样做 但没有成功 builder gt add points hidden array data gt 5000 any Idea 如果您想默认设置某些内容 请将其设置在模型对象上 model new
  • Javascript (ES6) 异步回调执行

    当许多异步函数排队时 它们的回调是顺序执行还是并发执行 它们按顺序运行 即使它们可能以异步方式排队 事件在浏览器的称为 Web API 的多线程区域中触发 触发事件 例如 XHR 请求 后异步地 一个事件循环同步地在 JavaScript
  • 好友模板重载运算符 <<:无法解析的外部符号

    我遇到了错误问题 错误 LNK2019 无法解析的外部符号 class std basic ostream gt cdecl cop4530 operator class rob Stack const 6rob YAAAV basic o
  • 初始化为数组的对象的 XML 序列化

    我的问题可能源于对 XML 序列化的基本误解 但无论如何 我正在尝试序列化一个包含对象的类 该对象是使用 XMLSerializer 类通过数组初始化的 最小的例子 using System using System IO using Sy
  • 实现抽象工厂模式的最佳方法

    考虑以下代码 include