Ответ 1
Совершенно прекрасно получить объект от статического метода.
например.
Одна из библиотек точек сети делает то же самое, что и вы,
XmlReadrer reader = XmlReader.Create(filepathString);
У меня есть класс, который определяет тип CallRate. Мне нужно добавить возможность создавать несколько экземпляров моего класса, читая данные из файла.
Я добавил статический метод в класс CallRate, который возвращает List<CallRate>
. Хорошо ли для класса генерировать новые экземпляры самого себя, вызывая один из его собственных конструкторов? Это работает, мне просто интересно, правильно ли это делать.
List<CallRates> cr = CallRates.ProcessCallsFile(file);
Совершенно прекрасно получить объект от статического метода.
например.
Одна из библиотек точек сети делает то же самое, что и вы,
XmlReadrer reader = XmlReader.Create(filepathString);
Уверен, что это хорошо, даже поощряется в некоторых случаях. Есть несколько шаблонов проектирования, которые касаются создания объектов, и некоторые из них делают только то, что вы описываете.
Я часто использую этот шаблон, когда мне нужно проверить правильность параметров. Категорически не рекомендуется бросать исключение из конструктора. Это не так плохо от метода factory, или вы можете выбрать null.
Кажется, мне хорошо. На других языках вы, вероятно, напишете функцию, но на языке, подобном С#, статические методы занимают эту роль.
Это нормально. То, что вы только что создали, похоже на простой метод factory. У вас есть статический метод, который создает допустимый экземпляр типа. На самом деле ваш метод даже не должен быть статичным, и у вас все еще есть действующий код. Существует шаблон дизайна (Prototype), который создает новый действительный объект из существующего объекта. Подробнее см. http://www.dofactory.com/Patterns/PatternPrototype.aspx.
Конечно, для простого разбора (или подобных) сценариев - я действительно предпочитаю factory method быть частью класса. Да - он прерывает SRP, но выполняет KISS - поэтому я называю это чистой победой. Для более крупных приложений или более сложных процедур синтаксического анализа - имеет смысл иметь внешний класс factory.
В вашем конкретном случае я бы предпочел метод, который использовался в IEnumerable <string> вместо имени файла - это все равно даст вам логику синтаксического анализа, но позволит легко тестировать единицы и "повторно использовать". Вызывающий может легко обернуть файл в IEnumerable.
Factory методы часто являются хорошей конструкцией. Когда я пишу их в С#, я называю их "New", чтобы:
new MyClass()
становится
MyClass.New()
Тривиально он реализован следующим образом:
class MyClass
{
public static MyClass New()
{
return new MyClass();
}
}
В основном я делаю это, когда есть дополнительные условия о том, действительно ли создавать класс или просто возвращать null
, или возвращать MyClass
или что-то, полученное из него.
Я иногда использую общедоступные статические методы как альтернативу перегрузке конструктора.
Особенно в ситуациях, когда нехорошо полагаться только на типы параметров, чтобы указать, какая конструкция объекта предназначена.
Я поклонник статических методов, возвращающих экземпляры, как было предложено много раз, выше.
@Paul: не забудьте пометить комментарий выше, который вы найдете, это лучший ответ.
Также как указать "генерировать новые экземпляры себя, вызывая один из своих собственных конструкторов"
Это не из конструктора, а из статического метода.
Обычно я использую это, когда мне нужны мгновенные реализации класса. Например
public class Car
{
public static Car RedExpensiveCar = new Car("Red", 250000);
public Car()
{
}
public Car(string color, int price)
{
Color = color;
Price = price;
}
public string Color { get; set; }
public int Price { get; set; }
}
И с этим мне не нужно запоминать или писать параметры конструктора в моем коде.
Car car = Car.RedExpensiveCar;
Это вполне приемлемо для этого. Когда я это делаю, я обычно делаю реальные конструкторы для класса private, так что он ясно, что единственный способ создания экземпляров - это статический метод.
Это очень полезно в тех случаях, когда "конструкция" может не всегда возвращать новый экземпляр. Например, вы можете захотеть вернуть ранее кэшированный объект.