工厂应该有一个带参数的构造函数
本文关键字:参数 构造函数 有一个 工厂 | 更新日期: 2023-09-27 18:34:24
假设我想构建一个字符串列表(这不是真实的场景情况,但听起来更容易解释)。
我会为我的字符串工厂列表提供一个界面,看起来像这样
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...
}
}
我知道这种方法会奏效,但我想知道它是否破坏了工厂模式以将参数传递给工厂的构造函数,这样我就不会破坏我的接口。这样做有没有对应物?还有我没有想到的另一种解决方案吗?我问的问题太多了吗?!(是的,我知道这个问题的答案!
构造
函数中的参数和构造函数本身应该只做一项工作:那就是注册依赖关系。有时,需要将依赖"注入"到工厂,正如 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...
}
}
它在这种情况下有效,但在您的情况下无效,因为:
- 它使您的工厂有状态
如果将参数(流)作为方法参数注入,则使您的工厂更加灵活
public class StringsListFromFile : IStringsListFactory{ public List<string> Create(StreamReader sr){ ///recover the strings using my stream reader... } }
如果您的接口应该灵活用于输入,请改用通用
- 此外,最好返回
IEnumerable<string>
而不是List<string>
你可以抽象出任何检索它的实现。我也会亲自将其传递到方法而不是构造函数中:
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());
对于这么小的样本来说,这一切似乎都很愚蠢......但我认为这并不像你的例子那么小。
工厂模式强制您使用默认构造函数。使用参数化构造函数违反了使用工厂模式的想法,因为对象不会将有效状态返回给调用方类。在这种情况下,您必须在工厂类调用后初始化它们。这将复制您的代码,使用工厂模式的想法是避免代码重复。但我同样不熟悉整个场景。但根据此处显示的设置,您应该使用一种方法代替参数化构造函数。