1

簡単な質問がありますが、答えがあるかどうかさえわかりませんが、試してみましょう。私はC++でコーディングしており、依存性注入を使用してグローバル状態を回避しています。これは非常にうまく機能し、予期しない/未定義の動作を頻繁に実行することはありません。

しかし、私のプロジェクトが成長するにつれて、ボイラープレートと見なす多くのコードを書いていることに気づきました。さらに悪いことに、実際のコードよりもボイラープレートコードが多いという事実により、理解が難しい場合があります。

良い例に勝るものはないので、行きましょう:

Timeオブジェクトを作成するTimeFactoryというクラスがあります。

詳細(関連性があるかどうかはわかりません):Timeはさまざまな形式を持つ可能性があり、それらの間の変換は線形でも単純でもないため、Timeオブジェクトは非常に複雑です。各「Time」には、変換を処理するためのシンクロナイザーが含まれています。正しく初期化された同じシンクロナイザーがあることを確認するために、TimeFactoryを使用します。TimeFactoryにはインスタンスが1つしかなく、アプリケーション全体であるため、シングルトンの対象になりますが、可変であるため、シングルトンにはしたくありません。

私のアプリでは、多くのクラスがTimeオブジェクトを作成する必要があります。これらのクラスは、深くネストされている場合があります。

クラスBのインスタンスを含むクラスAがあり、クラスDまでというようになります。クラスDはTimeオブジェクトを作成する必要があります。

私の素朴な実装では、TimeFactoryをクラスAのコンストラクターに渡し、クラスAのコンストラクターにTimeFactoryを渡し、クラスDまでクラスBのコンストラクターに渡します。

ここで、TimeFactoryのようなクラスがいくつかあり、上記のようなクラス階層がいくつかあると想像してください。依存性注入を使用すると、柔軟性と可読性がすべて失われます。

私のアプリに大きな設計上の欠陥がないかどうか疑問に思い始めています...それとも、これは依存性注入を使用するために必要な悪ですか?

どう思いますか ?

4

2 に答える 2

4

私の素朴な実装では、TimeFactoryをクラスAのコンストラクターに渡し、クラスAのコンストラクターにTimeFactoryを渡し、クラスDまでクラスBのコンストラクターに渡します。

これは、依存性注入の一般的な誤用です。クラスAがTimeFactoryを直接使用しない限り、TimeFactoryを表示、認識、またはアクセスすることはできません。Dインスタンスは、TimeFactoryを使用して構築する必要があります。次に、作成したばかりのDインスタンスを使用してCインスタンスを作成する必要があります。次に、BとC、最後にAとBです。これで、間接的にTimeFactoryにアクセスできるDインスタンスを所有するAインスタンスが作成され、AインスタンスはTimeFactoryが直接渡されるのを確認しませんでした。

MiškoHeveryがこのビデオでこれについて語っています。

于 2012-12-21T16:53:07.357 に答える
1

それが本当にグローバルであるならば、グローバルな状態は必ずしも悪ではありません。多くの場合、エンジニアリングのトレードオフがあり、依存性注入を使用すると、シングルトンインターフェイスやグローバル変数を使用するよりも多くの結合がすでに導入されていますTimeFactory。必要。クラスBとC、およびクラスCとDについても同じことが言えます。

シングルトンパターンを使用する次のソリューションを検討してください。

  1. (抽象)基本クラスに、アプリケーションの` TimeFactoryTimeFactoryへのシングルトンアクセスを提供させます。

  2. そのシングルトンを一度、具体的なサブクラスに設定しますTimeFactory

  3. TimeFactoryそのシングルトンを使用するためのすべてのアクセス権を持っています。

これによりグローバル状態が作成されますが、そのグローバル状態のクライアントは、その実装に関する知識から切り離されます。

潜在的な実装のスケッチは次のとおりです。

class TimeFactory
{
  public:
  // ...
  static TimeFactory* getSingleton(void) { return singleton; }

  // ...
  protected:
  void setAsSingleton(void)
  {
    if (singleton != NULL) {
      // handle case where multiple TimeFactory implementations are created
      throw std::exception();  // possibly by throwing
    }
    singleton = this; 
  }

  private:
  static TimeFactory* singleton = NULL;
};

のサブクラスTimeFactoryがインスタンス化されるたびsetAsSingletonに、コンストラクターまたは他の場所で、を呼び出すことができます。

于 2012-08-05T05:28:02.323 に答える