我想创建一个工厂来创建实现抽象接口的对象,该工具将返回对内部保留的对象的引用,并且不复制对象。这个想法与log4cxx / log4j Logger类设计中的想法非常相似。我还想尽可能多地隐藏客户端的详细信息,即查看暴露的.h文件不会泄露私有成员等实现细节。 例如:
EncryptorRef = Encryptor::getEncryptor("AES");
我想知道是否接受了此类设计的已发布指南/示例代码,因为我不想重新发明轮子,这项任务非常普遍。我想过使用静态工厂方法,里面的Singleton存储库,以及作为返回类型的具体对象的智能指针/引用。问题:
Encryptor
类定义了encryptor.h?非常感谢!
答案 0 :(得分:3)
使用智能指针作为返回值仅在客户端不再需要对对象的引用(例如,释放某些锁或其他资源或减少某些引用计数)时需要进行任何清理时才有用。如果不需要这样的话,我建议返回一个简单的参考。这样,客户端就知道他不必管理对象的生命周期或类似的东西。智能引用的标准实现是Boost.SmartPtr。 至于隐藏实现,只需将要公开的接口放入纯抽象基类中,让客户端通过工厂获取实例。他需要的只是具有抽象基类的标题,带有工厂声明的标题和要链接的二进制文件。
答案 1 :(得分:0)
为了隐藏实现细节,我建议使用pImpl习语。
答案 2 :(得分:0)
隐藏实现细节使加密类纯虚拟,没有数据。这使主标头文件保持简单,没有实现细节。如果要使用继承进行代码重用,那么使用像BaseEncryptionImpl这样的中间类(这将在私有/实现头文件中)。
只有实现静态工厂方法getEncryptor
的源文件必须包含加密实现。
此工厂方法应返回std::auto_ptr
而不是原始指针,以确保异常安全。备受诟病的auto_ptr
用于从函数返回指针。此外,它还减少了标头库与标准库的外部依赖关系,而不是提升。您班级的用户可以根据自己的需要使用boost::smart_prt
或boost::scoped_ptr
,两者都有auto_ptr
个构建器。
最初,我会尽可能简化getEncryptor
,可能会使用if else if
等来决定您应该创建哪个。这比在单例中实现AbstractFactory的注册表简单得多。大多数情况下,注册表只是在解决问题。你如何初始化注册表?您可以使用每个EncryptionImpl
类定义的静态对象,其构造函数注册和析构函数取消注册,但如果链接器决定您不需要这些对象,那么这可能会导致问题,因此不会将它们包含在您的可执行文件或库中
Encryptor.h
class Encryptor {
public:
virtual void encrypt(const Data & in, Data * out) = 0;
virtual ~Encryptor();
static std::auto_ptr<Encryptor> getEncryptor(const char * name);
};
Encryptor.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;
}
}
Client.cpp
void foo()
{
boost::scoped_ptr enc(Encryption::getEncryption("FOO"));
Data in = ...;
Data out = ...;
enc->encrypt(in, &out);
}