通过工厂设计模式从客户端隐藏新的优势是什么?

时间:2014-12-22 07:24:10

标签: c++ design-patterns factory-pattern

我最近已经阅读了工厂设计模式,因为他提到了正常方法中的一个问题是

*需要在客户端类中使用new关键字。

因此,通过使用工厂,我们已经实现了这一点(客户端不使用新的)。但是从客户端隐藏新的有什么好处?

一个问题是当客户端使用新的关键字时,他负责删除该内存。 如果我们也使用工厂,我们仍然需要这样做,当客户端在最后创建一个对象时,客户端必须删除它(工厂不会删除它们)。

据我所知,其他优点包括重用现有代码而无需更改客户端代码。但是我对从客户端隐藏新(甚至是类)所取得的成果感到困惑。

提前致谢。

4 个答案:

答案 0 :(得分:4)

我认为工厂模式的主要目的是“隐藏new客户端。”#34;主要目的是隐藏使用 new以及如何使用。"它使您可以自由地在实现中选择 您实际创建的类。

例如,您可以在工厂中提供界面Renderer

class Renderer
{
  // ...
};

struct RendererFactory
{
  Renderer* createRenderer() const;
};

Renderer* RendererFactory::createRenderer() const
{
#ifdef WIN32
  if (AskWinApiIfOpenGlEnabled())
    return new OpenGlRenderer();
  else
    return new DirectXRenderer();
#else
  return new OpenGlRenderer();
#endif
}

在C ++中,提供工厂功能的另一个好处是确保正确的内存管理。如果您更改上面的代码以返回std::unique_ptr<Renderer>(这是正确的事情),您可以保护客户端免受内存泄漏的影响(他们可以通过不调用返回值delete来做原始指针案例) 1

您甚至可能希望工厂保留对象的部分所有权(以便它可以重复使用它们),因此您可以执行以下操作:

class RendererFactory
{
  std::weak_ptr<Renderer> cachedRenderer;

public:
  std::shared_ptr<Renderer> createRenderer();
};

std::shared_ptr<Renderer> RendererFactory::createRenderer()
{
  if (auto r = cachedRenderer.lock())
    return r;
  auto r = std::make_shared<RendererSubClass>();
  cachedRenderer = r;
  return r;
}

总而言之,基于工厂的创建设计模式(抽象工厂和工厂方法)使您可以更好地控制创建和初始化的方式。


1 当然,通过createRenderer().release(),他们仍然可以通过Machiavelli进行内存泄漏,但那时他们就会采取积极的行动,而不仅仅是遗漏。

答案 1 :(得分:2)

工厂模式无意隐藏客户端对new的使用。是的,你必须在工厂内的新对象上调用delete。

工厂模式的主要优点是它可以在一个地方创建对象。因此,层次结构中的任何更改都只能影响代码的这么多部分,这只是一般规则的一个特殊规则,即软件中的任何更改都应该影响代码的最小部分

答案 2 :(得分:0)

一个优点是您不必担心创建对象所需的任何依赖项。通过使用工厂,您可以简单地抽象所需的所有引用。这主要是因为客户不需要创建也不必知道构建所需的详细信息。

答案 3 :(得分:0)

工厂模式(简单工厂,工厂方法和抽象工厂)都具有隐藏客户端产品创建细节的优势。它不仅仅是new,即使在创建对象时经常出现该关键字。还有很多其他细节,例如子类的名称,构造函数的参数等。重点是您要从客户端隐藏此信息,因为如果它发生更改,您只能在工厂中更新它(如果没有工厂,则与所有客户中的代码相对。)

您的问题的关键似乎是即使客户端没有使用new操作,处理内存的责任也不会消失。

有关于SO的相关问题:

我个人喜欢这样的想法:如果工厂有责任封装创建对象,那么它也应该包含解除创建对象的责任。也就是说,它应该具有delete方法(与create相反)。