Это хороший пример важности Liskov Substitution Principle. Я очень люблю изображение, используемое в this answer.
Если ваш класс имеет несколько конструкторов, и успех вашего метода зависит от того, какой конструктор был вызван, тогда у вас есть несколько вариантов.
Основная проблема заключается в том, что ваше состояние объекта зависит от того, какой конструктор вызван; это не лучшая технология проектирования, поскольку она приводит к распространению государственных проверок по всему классу, независимо от того, как вы представляете свою реализацию.
1) реорганизовать объекты на более мелкие объекты
Идея заключается в том, что ваш конструктор должен только требовать данных класса необходимых для запуска. Если у вас есть несколько конструкторов, каждый из которых требует различного количества аргументов и данных, тогда можно утверждать, что этот класс фактически представляет несколько разных объектов.
2) Принудительные требования к данным по методу.
public SearchWithTwoLevelCache(ISearchCore s, ICurrentTimeProvider tp)
{
//Initialize the two levels.
S=s;
lvl2 = TimeBoundedQueryCache(s.AsQueryDataSource, tp, TimeSpan(24,0,0));
lvl1 = SizeBoundedQueryCache(lvl2, 10);
}
Можно утверждать, что это состояние фактически не требует самого класса, так как, если он на самом деле является необходимым условием для функции, то сделать это требование самой функции. Это устраняет двусмысленность. Поэтому
Ваш класс может стать:
public SearchWithTwoLevelCache(ISearchCore s)
{
S = s;
}
public Whatever PerformTwoLevelSearch(ICurrentTimeProvider tp) { }
Например.
Идея здесь состоит в том, чтобы предоставить только данные в конструкторе, которые абсолютно необходимы для состояния всего класса.
Вы можете, конечно, осуществлять проверки на уровне метода и исключать исключения, но для людей, использующих ваш класс, это может оказаться очень неприятным.Как они знали, что для вызова функции 1 они должны были вызвать конструктор 2 и установить другую переменную? Как они узнают, какой интерфейс использовать? Вот почему сделать это условие функции намного проще и для использования, и для поддержания.
В будущем это также затруднит расширение этого класса. Если успех метода основан на вызове нескольких других методов или конструктора, то рефакторинг и изменение этой логики также заставят всех ваших клиентов тоже измениться.
Если существует несколько конструкторов, и ваш метод зависит от состояния объекта, на основе которого был вызван конструктор, вы можете захотеть переместить эти аргументы в сам вызов функции. Таким образом, у вас нет зависимостей от последовательности, и единственный способ, которым вы можете вызвать этот метод, - это данные, которые ему необходимы для успеха. – dash
«Лучший способ проверить, был ли экземпляр экземпляром надлежащим образом», вероятно, «не *» проверяет, был ли конструктор, используемый для того, чтобы SearchWithTwoLevelCache был выше ». – haim770