В любом месте, где вам нужно значение времени выполнения для построения конкретной зависимости, Абстрактная фабрика является решением.
Инициализация методов на интерфейсных запахах Leaky Abstraction .
В вашем случае я бы сказал, что вы должны смоделировать интерфейс IMyIntf
на , как вам нужно его использовать , а не на том, как вы намереваетесь создавать его реализации. Это деталь реализации.
Таким образом, интерфейс должен быть просто:
public interface IMyIntf
{
string RunTimeParam { get; }
}
Теперь определите абстрактную фабрику:
public interface IMyIntfFactory
{
IMyIntf Create(string runTimeParam);
}
Теперь вы можете создать конкретную реализацию IMyIntfFactory
, которая создает конкретные экземпляры IMyIntf
, например:
public class MyIntf : IMyIntf
{
private readonly string runTimeParam;
public MyIntf(string runTimeParam)
{
if(runTimeParam == null)
{
throw new ArgumentNullException("runTimeParam");
}
this.runTimeParam = runTimeParam;
}
public string RunTimeParam
{
get { return this.runTimeParam; }
}
}
Обратите внимание, как это позволяет нам защитить инварианты класса с помощью ключевого слова readonly
. Вонючие методы инициализации не нужны.
Реализация IMyIntfFactory
может быть такой простой:
public class MyIntfFactory : IMyIntfFactory
{
public IMyIntf Create(string runTimeParam)
{
return new MyIntf(runTimeParam);
}
}
У всех ваших потребителей, где вам нужен экземпляр IMyIntf
, вы просто берете зависимость от IMyIntfFactory
, запрашивая ее через Внедрение в конструктор .
Любой DI-контейнер, достойный своей соли, сможет автоматически подключить экземпляр IMyIntfFactory
для вас, если вы зарегистрируете его правильно.