実装の詳細を非表示にするには、Encryption クラスをデータなしで純粋仮想にします。これにより、プライマリ ヘッダー ファイルがシンプルになり、実装の詳細がなくなります。コードの再利用のために継承を使用する場合は、BaseEncryptionImpl のような中間クラスを使用します (これはプライベート/実装ヘッダー ファイルにあります)。
静的ファクトリ メソッドを実装するソース ファイルのみgetEncryptor
に、暗号化の実装を含める必要があります。
このファクトリ メソッドはstd::auto_ptr
、生のポインターではなく、例外を安全に返す必要があります。auto_ptr
関数からポインターを返すように設計されています。また、ブーストとは対照的に、ヘッダーの外部依存関係を標準ライブラリに減らします。クラスのユーザーは必要に応じてboost::smart_prt
またはを使用できます。どちらもコンストラクターを持っています。boost::scoped_ptr
auto_ptr
最初はgetEncryptor
できるだけシンプルに保ち、おそらくif else if
etc を使用して作成するものを決定します。これは、シングルトンで 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;
}
}
クライアント.cpp
void foo()
{
boost::scoped_ptr enc(Encryption::getEncryption("FOO"));
Data in = ...;
Data out = ...;
enc->encrypt(in, &out);
}