1

我想创建一个工厂来创建实现抽象接口的对象,这将返回对内部保存的对象的引用,并且不会复制对象。这个想法与 log4cxx/log4j Logger 类设计中的想法几乎相同。我还想尽可能多地向客户端隐藏细节,即查看暴露的 .h 文件不会显示私有成员等实现细节。示例:

EncryptorRef = Encryptor::getEncryptor("AES");

我想知道是否有针对此类设计的已发布指南/示例代码,因为我不想重新发明轮子,而且这项任务很常见。我想过使用静态工厂方法、内部单例存储库以及对具体对象的智能指针/引用作为返回类型。问题:

  • 这种设计是否有简单的示例代码?(log4cxx的代码太复杂,不能作为骨架使用)
  • 假设他只看到定义的 encryptor.h 纯抽象类,我如何完全隐藏客户端的存储库Encryptor
  • 你会建议使用智能引用或指针作为返回类型吗?是否有智能参考的标准实现?
  • 任何其他建议将不胜感激

多谢!

4

3 回答 3

3

仅当客户端不再需要对对象的引用时(例如释放一些锁或其他资源,或减少一些引用计数),需要任何清理时,使用智能指针作为返回值才有用。如果不需要这样的事情,我建议返回一个简单的参考。这样,客户就知道他不必管理对象的生命周期或类似的东西。智能引用的标准实现是 Boost.SmartPtr。至于隐藏实现,只要把要暴露的接口放到纯抽象基类中,让客户端通过工厂获取实例即可。他所需要的只是带有抽象基类的头文件、带有工厂声明的头文件和要链接到的二进制文件。

于 2009-11-26T11:36:31.903 回答
0

为了隐藏实现细节,我建议使用 pImpl 成语。

于 2009-11-26T11:22:37.700 回答
0

为了隐藏实现细节,使 Encryption 类成为纯虚拟的,没有数据。这使主头文件保持简单并且没有实现细节。如果您想使用继承来重用代码,请使用像 BaseEncryptionImpl 这样的中间类(这将在私有/实现头文件中)。

只有实现静态工厂方法的源文件getEncryptor必须包含加密实现。

这个工厂方法应该返回一个std::auto_ptr与原始指针相反的异常安全的指针。备受诟病auto_ptr的是为从函数返回指针而设计的。此外,它还减少了头文件对标准库的外部依赖,而不是 boost。您的类的用户可以使用boost::smart_prtboost::scoped_ptr根据他们的需要使用,两者都有auto_ptr构造函数。

最初我会getEncryptor尽可能简单,可能使用if else if等来决定你应该创建哪个。这比在单例中实现 AbstractFactory 的注册表要简单得多。大多数时候,注册表只是解决问题。你如何初始化注册表?您可以使用每个EncryptionImpl类定义的静态对象,其构造函数注册而析构函数注销,但如果链接器决定您不需要这些对象,因此不将它们包含在可执行文件或库中,这可能会导致问题。

加密器.h

class Encryptor {
public:
  virtual void encrypt(const Data & in, Data * out) = 0;
  virtual ~Encryptor();

  static std::auto_ptr<Encryptor> getEncryptor(const char * name);
};

加密器.cpp

#include "Encryptor.h"
#include "EncryptorA.h"
#include "EncryptorB.h"

std::auto_ptr<Encryptor> Encryptor::getEncryptor(const char * name)
{
  // EncryptorA::NAME is a std::string
  if (EncryptorA::NAME == name) {
    return std::auto_ptr<Encryptor>(new EncryptorA);
  }
  else if (EncryptorB::NAME == name) {
    return std::auto_ptr<Encryptor>(new EncryptorB);
  }
  else {
    throw EncryptionNotDefined;
  }
}

客户端.cpp

void foo()
{
  boost::scoped_ptr enc(Encryption::getEncryption("FOO"));

  Data in = ...;
  Data out = ...;

  enc->encrypt(in, &out);
}
于 2009-11-26T18:52:00.323 回答