Похоже, вы уже определили шаблон. Это шаблон фабричного метода . Или, скорее, несколько недоделанная реализация одного. Немного лучшим подходом было бы сначала сделать его интерфейсом:
public interface IArticleFactory
{
IArticle CreateArticle(string sku);
}
Затем реализуем фабрику без какого-либо отражения:
public class MyArticleFactory
{
private Dictionary<string, Func<IArticle>> instantiators =
new Dictionary<string, Func<Iarticle>>();
public MyArticleFactory()
{
Register("Jeans", () => new Jeans());
Register("Shirt", () => new Shirt());
// etc.
}
public IArticle CreateArticle(string sku)
{
Func<IArticle> instantiator;
if (creators.TryGetValue(sku, out instantiator))
return instantiator();
throw new UnknownSkuException(sku);
}
protected void Register(string sku, Func<IArticle> instantiator)
{
creators.Add(sku, instantiator);
}
}
Несколько важных отличий:
Регистрация не является публичной и не должна быть. Обычно регистрация либо находится в файле конфигурации, либо является частной.
Не требуется, чтобы конкретные типы IArticle
имели конструктор по умолчанию без параметров. Это может легко зарегистрировать статьи с параметризованными конструкторами (при условии, что они знают, какие параметры использовать).
Выдает исключение при повторных регистрациях. Мне не нравится идея простого возвращения false
; если вы попытаетесь зарегистрировать один и тот же фабричный метод дважды, это следует считать ошибкой.
Это не статично. Вы можете заменить этот завод другим заводом. Вы можете протестировать его.
Конечно, еще лучшим подходом было бы просто использовать любое из множества существующих .NET инъекций / инверсий зависимостей, таких как Ninject или AutoFac .