6

文字列のリストを作成したいとしましょう (これは実際のシナリオではありませんが、説明が簡単に聞こえます)。

このような文字列ファクトリのリストのインターフェースがあります

public interface IStringsListFactory{
   List<string> Create();
}

しかし、私の具体的な工場の1つが、ファイル/データベースなどからこの文字列のリストを取得する必要があるとしましょう..

public class StringsListFromFile : IStringsListFactory{

   private StreamReader _streamReader;
   public StringsListFromFile(StreamReader sr) //StreamReader is just an example.
   {
       _streamReader = sr;
   }

   public List<string> Create(){ 
     ///recover the strings using my stream reader... 
   }
}

このアプローチが機能することはわかっていますが、ファクトリ パターンを壊してファクトリのコンストラクタにパラメータを渡して、インターフェイスを壊さないようにするかどうか疑問に思っていました。これを行うことに対応するものはありますか?私が考えていなかった別の解決策はありますか?質問しすぎですか!?(ええ、私はこれに対する答えを知っています!)

4

3 に答える 3

4

コンストラクターのパラメーター、およびコンストラクター自体は、実行するジョブを 1 つだけ実行する必要があります。つまり、依存関係を登録します。この回答の Mark Seeman による抽象ファクトリ パターン で説明されているように、依存関係をファクトリに「注入」する必要がある場合があります。

public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
    private readonly IProfileRepository aRepository;
    private readonly IProfileRepository bRepository;

    public ProfileRepositoryFactory(IProfileRepository aRepository,
        IProfileRepository bRepository)
    {
        if(aRepository == null)
        {
            throw new ArgumentNullException("aRepository");
        }
        if(bRepository == null)
        {
            throw new ArgumentNullException("bRepository");
        }

        this.aRepository = aRepository;
        this.bRepository = bRepository;
    }

    public IProfileRepository Create(string profileType)
    {
        if(profileType == "A")
        {
            return this.aRepository;
        }
        if(profileType == "B")
        {
            return this.bRepository;
        }

        // and so on...
    }
}

その場合は有効ですが、あなたの場合はそうではありません:

  1. それはあなたの工場に状態を持たせます
  2. パラメータ(ストリーム)がメソッドパラメータとして注入されると、ファクトリがより柔軟になります

    public class StringsListFromFile : IStringsListFactory{
    
       public List<string> Create(StreamReader sr){ 
         ///recover the strings using my stream reader... 
       }
    }
    
  3. インターフェイスが入力に対して柔軟である必要がある場合は、代わりにジェネリックを使用してください

  4. IEnumerable<string>さらに、代わりに戻る方が良いList<string>
于 2013-10-08T05:43:59.807 に答える
0

それを取得するものの実装を抽象化できます。また、コンストラクターではなくメソッドに個人的に渡します。

public interface IFactoryDataSourceProvider<T> {
    IList<T> GetData();
}

public class IStringListFactory {
    public IList<string> Create(IFactoryDataSourceProvider<string> provider) {
        return _provider.GetData();
    }
}

次に、おそらく:

class StreamReaderDataProvider : IFactoryDataSourceProvider<string> {
    public IList<string> GetData() {
        using (var streamReader = new StreamReader( ... )) {
            return streamReader.ReadAllLines(); // etc.
        }
    }
}

var list = factory.Create(new StreamReaderDataSourceProvider());

これは、このような小さなサンプルではばかげているように思えます..しかし、これはあなたの例ほど小さくはないと思います。

于 2013-10-08T03:03:45.390 に答える