Используйте свойство как фабричный метод
У меня есть базовый класс Base
который должен создавать экземпляры другого типа TRequired
однако, только производные классы от Base
знать, как их построить.
Это плохой стиль - использовать абстрактное свойство как метод фабрики? например
protected abstract TRequired NewTRequired { get; }
Должен ли я использовать метод по какой-то причине? Есть ли руководство, почему я не должен / не должен использовать собственность здесь?
3 ответа
Вы обязательно должны использовать метод, потому что доступ к этому члену делает что-то. Вызов метода - хороший способ позволить коду говорить за себя в этом отношении.
Или, если вы предпочитаете другую перспективу: два последующих доступа к члену будут возвращать разные результаты. Хорошее эмпирическое правило заключается в том, чтобы использовать метод всякий раз, когда это имеет место, чтобы не нарушать принцип наименьшего удивления.
Похоже, что он читает результат переменной, даже если вы знаете, что NewTRequired
это свойство (в отличие от поля), вы также знаете, что в действительности он выполняет произвольный код:
var prototype = Factory.NewTRequired;
Я намеренно поместил результат в переменную prototype
чтобы лучше показать, что даже осведомленный читатель этого кода может быть легко сброшен: было бы неразумно видеть это и думать "правильно, так NewTRequired
является прототипом объекта для X". Этот читатель наверняка будет удивлен результатом кода, подобного этому:
var eq = object.ReferenceEquals(prototype, Factory.NewTRequired);
Сравните это с заводским методом. Теперь этот код может издавать слабый запах:
// hmmm... are we actually using this as a prototype?
// because it sure looks like an instance created just for the occasion.
var prototype = Factory.NewTRequired();
И этот код никогда не удивит вас:
// obviously should be false, the code screams "I am creating new instances!"
var eq = object.ReferenceEquals(Factory.NewTRequired(), Factory.NewTRequired());
Известный пример, где это правило действительно следовало, но не было DateTime.Now
имущество.
Я бы порекомендовал метод вместо:
protected abstract TRequired CreateRequired();
Творение подразумевает "работу" происходящего. Это лучше подходит для метода по сравнению со свойством, поскольку средство получения свойства подразумевает что-то, что обычно будет возвращаться быстро без выполнения большого количества кода.
Даже название вопроса "свойство как фабричный метод" подразумевает, что фабричный метод должен быть методом.
Свойства предназначены для вещей, которые похожи на поля, такие как местоположение объекта.
Свойство, которое каждый раз возвращает новый экземпляр, очень плохой дизайн.
Вы должны использовать метод вместо этого.