1

次のように、建設後もファクトリーに属している何らかの種類のファクトリー作成リソースがあると仮定します。

public class Resource : IDisposable {
  public void Dispose() { /* ... */ }
}

public class ResourceManager : IDisposable {
  public Resource Load() { /* create resource and add to list */ }
  public void Dispose() { /* dispose all loaded resources in list */ }
}

Resourceこれで、コンストラクターで初期化するインスタンスを必要とする基本クラスができました。

public class Fooificator {
  public Fooificator(Resource resource) {
    this.resource = resource;
  }
  private Resource resource;
}

このような基本クラスから派生したクラスはResource、ファクトリへの参照を失わずに a を構築するにはどうすればよいでしょうか?

静的メソッドを使用する素朴なアプローチには、ファクトリを記憶する方法がありません (基本クラスの構築が終了した後にコンストラクターが取得できるように静的フィールドに格納する、または 2 段階の初期化を使用するなどの醜いハックを除くResource) 。コンストラクターによって呼び出されたInitialize()メソッドを介して基本クラスに与えられます)

public class DefaultFooificator : Fooificator {
  public DefaultFooificator() : base(loadDefaultResource()) {}

  private static Resource loadDefaultResource() {
    ResourceManager resourceManager = new ResourceManager();
    return resourceManager.Load();
    // Bad: losing reference to ResourceManager here!
  }
}

考えられる回避策の 1 つは、名前付きコンストラクターのイディオムです。

public class DefaultFooificator : Fooificator, IDisposable {

  public static DefaultFooificator Create() {
    ResourceManager resourceManager = new ResourceManager();
    DefaultFooificator fooificator = new DefaultFooificator(
      resourceManager.Load()
    );
    fooificator.resourceManager = resourceManager;

    return fooificator;
  }

  private DefaultFooificator(Resource resource) : base(resource) {}
  private ResourceManager resourceManager;
}

ただし、ResourceManager参照を格納する問題は解決されますが、DefaultFooificator.

参照をさらに派生させたり、他の方法でDefaultFooificator保存したりできるエレガントなソリューションはありますか?ResourceManager

4

2 に答える 2

1

クラスが緊密に結合されていないかどうかを検討する必要があると思います。Resourceにパブリックコンストラクターがある場合、誰でもインスタンスを作成し、それをFooificatorコンストラクターへの参照として渡すことができます。それは実際には良いことです。

あまり魅力的ではないように思われるのは、ResourceManager.Loadによって作成されたリソース(BTW、これはコマンド/クエリ分離の違反です)のみを合法的に使用できるという要件があるように見えることです。ただし、APIはこの制約を強制しません。

Resourceコンストラクターを内部にするか、ResourceManager制約を解除することにより、この制約を適用する必要があります。

内部コンストラクターはクラスの密結合の方向に引っ張る傾向があるので、2番目のオプションを真剣に検討します。

または、Fooificatorのコンストラクターを変更して、ResourceManagerまたはおそらく。への参照を取得しますFunc<ResourceManager, Resource>

より多くの文脈がなければ、より良い答えを出すことは難しいと思います。

于 2009-08-25T10:27:35.207 に答える
1

から派生したクラスFooificatorが の構築を担当する必要があるのはなぜResourceですか? この依存関係をコンストラクターに挿入できないのはなぜですか?

public class DefaultFooificator : Fooificator
{
    public DefaultFooificator(Resource resource) : base(resource) {}
}

リソースの作成をFooificatorFactory.

于 2009-08-25T10:18:14.897 に答える