c++ - C++ 抽象工厂是否应该为构造的对象提供 destroy 方法?

标签 c++ oop c++98 creation-pattern

考虑下面的接口(interface)(使用哑指针是因为我们还在 C++98)

class WidgetMaker {
    virtual Widget* makeWidget() = 0;
};

具有以下可能的实现

class SpecificWidgetMaker: public WidgetMaker {
    Widget* makeWidget() {
        return new SpecificWidget();
    }
};

Widget 是一些具有虚析构函数的基类,SpecificWidget 扩展了它。 我的同事声称 WidgetMaker 接口(interface)应该包含以下方法

virtual void freeWidget(Widget* widget);

基本原理是这样我们不会强制 makeWidget 实现使用标准的新分配,它们可以使用自定义池分配器或始终返回相同的全局实例以防小部件是无状态的或其他。

我觉得这样的设计通常是个坏主意——它使客户端代码复杂化,违反了 KISS 和 YAGNI,使向 unique_ptr 的过渡(在未来 20 年内不太可能在我们的组织中发生)变得更加困难。我应该相信自己的感觉吗?在哪些情况下,自由方法作为抽象工厂接口(interface)的一部分是合理的?

最佳答案

您 friend 提出的解决方案(实际上,您的原始解决方案也是如此)的一个问题是它有一个不必要的非平凡协议(protocol)。一旦您通过 makeWidget 获得了一个 Widget,您需要记住释放它(直接释放,或调用工厂的某些方法)。众所周知,这是脆弱的 - 它会很快崩溃(导致 Widget 泄漏),或者真正使客户端代码复杂化。

如果你看std::shared_ptr::shared_ptr(...)的界面,您可以看到它可以采用自定义删除器对象

因此,也许您可​​以typedef(或等效的)Widget 智能指针到底是什么:

using WidgetPtr = std::shared_ptr<Widget, ...>

如果您稍后决定工厂需要在释放 Widget 时执行某些操作,您可以将 typedef 更改为使用自定义删除器的类型,并且这个自定义删除器可以通知工厂一个对象正在被删除。

这样做的主要优点是它消除了用户记住释放 Widget 的责任。

关于c++ - C++ 抽象工厂是否应该为构造的对象提供 destroy 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35316480/

相关文章:

c++ - 使用cmd通过ftp传输文件

c++ - 如何使用 std::variant 打印映射键/值?

python - 在 Python 3 中扩展一个类并使用 __init__ 构造它

c++ - 用 boost::assign::list_of 初始化一个 std::vector<std::vector<int>>

c++ - 从文本文件创建二维字符串 vector

c++ - 在 C++ 中从标量到非标量的转换

Javascript 类,事件监听器中的 var 未定义

java - 通过属性获取实例化对象

c++ - 按排序顺序迭代 std::vector

c++ - 为 map 重载 "<<"运算符