Опубликовано 12 августа 2021 г.

Я использовал расширение интерфейса в java без проблем в течение многих лет и никогда не задумывался о том, можно ли это сделать по-другому. Недавно я экспериментировал с идеей, и, кажется, она окупается.

Мы все знаем, что композиция классов вместо наследования — это путь. Но что происходит, когда мы применяем это к интерфейсам?

Пример

Давайте нарисуем пример проблемы здесь. У меня есть три вида записей. Базовый содержит только данные и ничего не знает о своей схеме. Второй знает о схеме. А третий является лишь специализацией двух вышеперечисленных и представляет собой единую запись.

Обычно я бы сделал

Это может быть не лучший дизайн, но обычно я видел это большую часть своей карьеры.

Вы также можете возразить, что при реализации необходимо реализовать комбинацию этих интерфейсов, поэтому нет смысла их расширять. НО SingleRecord в этом случае всегда должен быть проходим, поэтому я хочу встроить эту информацию в код.

Что я сделал по-другому на этот раз, так это

Наследование исчезло, но информация о том, что SingleRecord также доступна для обхода, все еще присутствует.

С точки зрения расширения реализация SingleRecord должна была бы реализовать все методы и делегировать их или реализовать заново. В последнем случае он может вернуть делегированную реализацию или вернуть новую на основе некоторого условия. И это всего лишь один метод вместо всех унаследованных, что сокращает шаблонный код и уменьшает дублирование. Это также полезно при добавлении нового метода в интерфейс, который не приводит к поломке всех реализаторов дочернего интерфейса.

Также при тестировании он позволяет мне заглушить простой интерфейс и вернуть null/выдать исключение для унаследованного, если его методы не используются.

На данный момент этот подход прошел несколько юзабилити-тестов с течением времени, и кажется, что его стоит принять еще.