C++ 在C+中使用对象存储库构建工厂+;?
我想创建一个工厂,用于创建实现抽象接口的对象,该接口将返回对内部保存的对象的引用,而对象不会被复制。这个想法与log4cxx/log4j记录器类设计中的想法几乎相同。我还希望尽可能多地隐藏客户机的详细信息,即查看暴露的.h文件不会显示私有成员等实现细节。 例如: 我想知道是否有为此类设计发布的指南/示例代码,因为我不想重新发明轮子,而且这项任务非常常见。我考虑使用静态工厂方法、内部的单例存储库,以及对具体对象的智能指针/引用作为返回类型。问题:C++ 在C+中使用对象存储库构建工厂+;?,c++,design-patterns,oop,factory-pattern,C++,Design Patterns,Oop,Factory Pattern,我想创建一个工厂,用于创建实现抽象接口的对象,该接口将返回对内部保存的对象的引用,而对象不会被复制。这个想法与log4cxx/log4j记录器类设计中的想法几乎相同。我还希望尽可能多地隐藏客户机的详细信息,即查看暴露的.h文件不会显示私有成员等实现细节。 例如: 我想知道是否有为此类设计发布的指南/示例代码,因为我不想重新发明轮子,而且这项任务非常常见。我考虑使用静态工厂方法、内部的单例存储库,以及对具体对象的智能指针/引用作为返回类型。问题: 这种设计有简单的代码示例吗?(log4cxx的代
- 这种设计有简单的代码示例吗?(log4cxx的代码太复杂,无法用作骨架)
- 假设客户机只看到纯抽象的
class-defined Encryptor.h,我如何对客户机完全隐藏存储库Encryptor
- 您是否建议使用智能引用或指针作为返回类型?是否有智能参考的标准实施
- 如有其他建议,将不胜感激
非常感谢 为了隐藏实现细节,我建议使用pImpl习惯用法。只有当客户端不再需要对对象的引用时(例如,释放一些锁或其他资源,或减少一些引用计数),需要进行任何清理时,才使用智能指针作为返回值。如果没有必要这样做,我建议返回一个简单的参考。这样,客户机就知道他不必管理对象的生命周期或类似的事情。智能引用的标准实现是Boost.SmartPtr。
至于隐藏实现,只需将要公开的接口放入纯抽象基类中,并让客户机通过工厂获取实例。然后,他只需要带有抽象基类的头、带有工厂声明的头和要链接到的二进制文件。要隐藏实现细节,请将加密类设置为纯虚拟的,没有数据。这使得主头文件保持简单,并且没有实现细节。如果您想使用继承来重用代码,那么可以使用像BaseEncryptionImpl这样的中间类(这将在私有/实现头文件中) 只有实现静态工厂方法的源文件
getEncryptor
必须包含加密实现
此工厂方法应返回一个std::auto_ptr
,而不是一个原始指针,以确保异常安全。备受诟病的auto_ptr
是为从函数返回指针而设计的。此外,它还将标头的外部依赖项减少到标准库,而不是boost。您的类的用户可以根据自己的需要使用boost::smart_prt
或boost::scoped_ptr
,两者都有auto_ptr
构造函数
起初,我会尽可能简单地使用getEncryptor
,可能使用if-else-if
等来决定应该创建哪个。这比在单例中实现AbstractFactory注册表要简单得多。大多数时候,注册中心只是在转移问题。如何初始化注册表?您可以使用每个EncryptionImpl
类定义的静态对象,其构造函数注册,析构函数注销,但如果链接器确定您不需要这些对象,因此不将它们包含在可执行文件或库中,则这可能会导致问题
加密机
class Encryptor {
public:
virtual void encrypt(const Data & in, Data * out) = 0;
virtual ~Encryptor();
static std::auto_ptr<Encryptor> getEncryptor(const char * name);
};
隐藏的第一步是提供一个函数,并在内部保留完整的工厂类。没错,因此我猜它应该是工厂方法实现中使用的一个单例?不一定:您也可以使用
pimpl
习惯用法让一个类实例化工厂,这允许有多个工厂。。。如果你觉得有道理的话。然而,在大多数情况下,这些工厂确实是独一无二的,因此实现为Singleton
。非常感谢您的详细回答!不过,我有以下顾虑:我希望(需要调查)每种类型都有一个具体的对象,并与所有客户共享。这是因为某些对象将具有相当大的缓存,构建它们需要读取配置。如果我为客户端克隆对象,我需要实现一些缓存共享机制。一种选择是按名称(某处)保存对象的静态映射,或者在启动时构造所有对象,或者在请求时检查是否已构造对象?要共享具体对象,您可能应该返回一个共享\u ptr。预创建对象和按需创建对象都有好处。预创建可能会减慢启动速度并使用比所需更多的内存,但会有助于解决getEcryption()中的线程问题。Ondemand具有更快的启动速度,但对getEcryption的调用可能具有不可预测的时间,而且实现起来也更复杂。如果您不介意复杂的实现并希望提高内存效率,那么可以将弱ptr存储在缓存中。
class Encryptor {
public:
virtual void encrypt(const Data & in, Data * out) = 0;
virtual ~Encryptor();
static std::auto_ptr<Encryptor> getEncryptor(const char * name);
};
#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;
}
}
void foo()
{
boost::scoped_ptr enc(Encryption::getEncryption("FOO"));
Data in = ...;
Data out = ...;
enc->encrypt(in, &out);
}