Каждый класс реализует интерфейс (то есть контракт), поскольку он предоставляет не приватный API. Нужно ли вам представлять интерфейс отдельно, как интерфейс Java, зависит от того, является ли реализация «концепцией, которая меняется».
Если вы абсолютно уверены, что существует только одна разумная реализация, тогда нет необходимости в интерфейсе. В противном случае интерфейс позволит вам изменить реализацию без изменения клиентского кода.
Некоторые люди будут кричать «ЯГНИ», предполагая, что у вас есть полный контроль над изменением кода, если позже вы обнаружите новое требование. Другие люди будут справедливо бояться, что им нужно будет изменить неизменяемый - опубликованный API.
Если вы не реализуете интерфейс (и используете какую-то фабрику для создания объекта), то определенные виды изменений заставят вас нарушить принцип Открыто-Закрыто. В некоторых ситуациях это коммерчески приемлемо, в других - нет.
Можете ли вы описать ситуацию, когда не очень хорошая идея использовать интерфейсы?
В некоторых языках (например, C ++, C #, но не в Java) вы можете получить выигрыш в производительности, если ваш класс не содержит виртуальных методов.
В небольших программах или приложениях без опубликованных API-интерфейсов вы можете столкнуться с небольшими затратами на обслуживание отдельных интерфейсов.
Если вы видите значительное увеличение сложности из-за разделения интерфейса и реализации, то вы, вероятно, не используете интерфейсы в качестве контрактов. Интерфейсы снижают сложность. С точки зрения потребителя, компоненты становятся товарами, которые выполняют условия контракта, а не субъектами, которые имеют сложные детали реализации сами по себе.