3

私は設計パターンとその周辺のもの (特にSOLIDDependency inversionの原則など) を学んでおり、何かを失っているように見えます:

DIPルールに従って、クラス内にオブジェクトを作成するのではなく ( composition )、オブジェクト参照/ポインターをクラス コンストラクターに送信する ( aggregation )ことで、クラスの脆弱性を軽減できるはずです。しかし、これは、別の場所でインスタンスを作成する必要があることを意味します。したがって、集約を使用する 1 つのクラスがより柔軟であるほど、他のクラスはより壊れやすくなります。

どこが間違っているのか説明してください。

4

3 に答える 3

5

アイデアを論理的な結論までたどるだけです。はい、インスタンスを別の場所に作成する必要がありますが、これはクラスの 1 レベル上のクラスだけではない可能性があります。オブジェクトがアプリケーションの非常に外側のレイヤーでのみ作成されるまで、押し出したり外したりする必要があります。

理想的には、すべてのオブジェクトを 1 か所で作成します。これはコンポジション ルートと呼ばれます (ファクトリから作成されたオブジェクトは例外ですが、ファクトリはコンポジション ルートで作成されます)。これが正確にどこにあるかは、構築しているアプリの種類によって異なります。

  • デスクトップ アプリでは、それは Main メソッドにあります (またはそれに非常に近い)。
  • ASP.NET (MVC を含む) アプリケーションでは、Global.asax にあります。
  • WCF では、それは ServiceHostFactory にあります。

この場所は「脆弱」になる可能性がありますが、アプリケーションを再構成できるようにするために変更できる場所は 1 つしかなく、他のすべてのクラスはテスト可能で構成可能です。

この優れた回答を参照してください(上記で引用されています)

于 2015-02-24T21:21:58.523 に答える
0

はい、クラスをどこかでインスタンス化する必要があります。DIP に正しく従うと、すべてのインスタンスを 1 か所に作成することになります。この場所をクラス編成と呼んだ。このトピックに関するより深い理解についての私のブログを読んでください。

于 2016-06-03T02:11:18.663 に答える
0

見落としている重要な可能性の 1 つは、クラス自体ではなく、ファクトリの注入です。これの利点の 1 つは、インスタンスの所有権をより明確にできることです。コンポーネントの所有権をコンテナーに明示的に与えているため、コードが少し見にくいことに注意してください。shared_ptrではなく ,を使用すると、物事が少しすっきりする可能性がありますunique_ptrが、所有権があいまいになります。

したがって、次のようなコードから始めます。

struct MyContainer {
  std::unique_ptr<IFoo> foo;
  MyContainer() : foo(new Foo() ) {};
  void doit() { foo->doit(); }
}

void useContainer() {
   MyContainer container;
   container.doit();
}

非工場バージョンは次のようになります

struct MyContainer {
  std::unique_ptr<IFoo> foo;
  template<typename T>
  explicit MyContainer(std::unique_ptr<T> && f) :
     foo(std::move(f))
  {}
  void doit() { foo->doit(); }
}

void useContainer() {
   std::unique_ptr<Foo> foo( new Foo());
   MyContainer container(std::move(foo));
   container.doit();
}

工場出荷時のバージョンは次のようになります

struct FooFactory : public IFooFactory {
  std::unique_ptr<IFoo> createFoo() override {
    return std::make_unique<Foo>();
  }
};

struct MyContainer {
  std::unique_ptr<IFoo> foo;
  MyContainer(IFooFactory & factory) : foo(factory.createFoo()) {};
  void doit() { foo->doit(); }
}

void useContainer() {
   FooFactory fooFactory;
   MyContainer container(fooFactory);
   container.doit();
}

IMO が C++ の所有権と有効期間について明示することは重要です。これは C++ のアイデンティティの重要な部分です。これは RAII や他の多くの C++ パターンの中心にあります。

于 2016-06-03T02:41:22.233 に答える