6

假设我想构建一个字符串列表(这不是真实的场景案例,但听起来更容易解释)。

我的字符串工厂列表有一个界面,看起来像这样

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

但是可以说我的一个具体工厂需要从文件/数据库等中获取这个字符串列表。

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

构造函数中的参数,以及构造函数本身,应该只做一件且唯一的工作:注册依赖。有时,需要将依赖项“注入”到工厂,正如 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 回答
0

工厂模式强制您使用默认构造函数。使用参数构造函数违反了使用工厂模式的想法,因为对象不会将有效状态返回给调用者类。在您的情况下,您必须在工厂类调用之后初始化它们。这将复制您的代码,使用工厂模式的想法是避免代码重复。但是我又不熟悉整个场景。但是根据您在此处显示的设置,您应该使用一种方法来代替参数构造函数。

于 2013-10-08T04:23:39.673 回答