1

内部に保持されているオブジェクトへの参照を返す抽象インターフェイスを実装するオブジェクトを作成するためのファクトリを作成したいのですが、オブジェクトは複製されません。考え方は、log4cxx/log4j Logger クラスの設計とほとんど同じです。また、できるだけ多くの詳細をクライアントから隠したいと思います。つまり、公開された .h ファイルを表示しても、プライベート メンバーなどの実装の詳細は明らかになりません。例:

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

私は車輪を再発明したくないので、そのような設計のための公開されたガイドライン/サンプルコードが受け入れられたかどうか疑問に思います.タスクはかなり一般的です. 静的ファクトリ メソッド、内部のシングルトン リポジトリ、および返される型として具体的なオブジェクトへのスマート ポインター/参照を使用することを考えました。質問:

  • そのような設計のためのサンプルの簡単なコードはありますか? (log4cxx のコードは複雑すぎてスケルトンとして使用できません)
  • Encryptor純粋な抽象クラスで定義されたencryptor.hしか見えないと仮定して、クライアントからリポジトリを完全に隠すにはどうすればよいですか?
  • 戻り値の型としてスマート参照またはポインターを使用することをお勧めしますか? スマート参照の標準実装はありますか?
  • 他の提案をいただければ幸いです

どうもありがとう!

4

3 に答える 3

3

スマートポインタを戻り値として使用することは、クライアントがオブジェクトへの参照を必要としなくなったときにクリーンアップが必要な場合にのみ役立ちます(たとえば、ロックやその他のリソースを解放したり、参照カウントを減らしたりします)。そのようなことが必要ない場合は、簡単な参照を返すことをお勧めします。このようにして、クライアントは、オブジェクトのライフサイクルなどを管理する必要がないことを認識します。スマート参照の標準的な実装はBoost.SmartPtrです。実装を非表示にする場合は、公開するインターフェイスを純粋な抽象基本クラスに配置し、クライアントがファクトリを介してインスタンスを取得できるようにします。その場合、彼が必要とするのは、抽象基本クラスを含むヘッダー、ファクトリ宣言を含むヘッダー、およびリンクするバイナリーだけです。

于 2009-11-26T11:36:31.903 に答える
0

実装の詳細を非表示にするには、Encryption クラスをデータなしで純粋仮想にします。これにより、プライマリ ヘッダー ファイルがシンプルになり、実装の詳細がなくなります。コードの再利用のために継承を使用する場合は、BaseEncryptionImpl のような中間クラスを使用します (これはプライベート/実装ヘッダー ファイルにあります)。

静的ファクトリ メソッドを実装するソース ファイルのみgetEncryptorに、暗号化の実装を含める必要があります。

このファクトリ メソッドはstd::auto_ptr、生のポインターではなく、例外を安全に返す必要があります。auto_ptr関数からポインターを返すように設計されています。また、ブーストとは対照的に、ヘッダーの外部依存関係を標準ライブラリに減らします。クラスのユーザーは必要に応じてboost::smart_prtまたはを使用できます。どちらもコンストラクターを持っています。boost::scoped_ptrauto_ptr

最初はgetEncryptorできるだけシンプルに保ち、おそらくif else ifetc を使用して作成するものを決定します。これは、シングルトンで 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);
}
于 2009-11-26T18:52:00.323 に答える
0

実装の詳細を隠すには、pImpl イディオムを使用することをお勧めします。

于 2009-11-26T11:22:37.700 に答える