Здравствуйте, Буравчик, Вы писали:
Б>Чем руководствуетесь, принимая решение выделять или не выделять интерфейс из класса, т.е. нужно ли разделить интерфейс и реализацию?
Б>Когда имеется несколько реализация — понятно, интерфейс обычно выделяют.
Б>Но если реализация только одна, для каких классов выделяете интерфейсы, а для каких нет?
Б>P.S. Возможно, ответ сильно зависит от используемого языка. По возможности, укажите используемый язык.
Мой ответ будет зависеть от ЯП, потому что в разных ЯП могут быть разные причины хотеть выделить интерфейс.
Отвечу в контексте Java. Выделяю интерфейс когда компонент решает более общую задачу, чем та, которую нужно решить в этой конкретной ситуации. Если во всём коде эта проблема встречается всего 1 раз и именно вот в таком виде, то есть варианты:
1. Заточить решение под эту конкретную ситуацию.
2. Оставить решение общим, и просто, да, использовать его всего 1 раз для этой конкретной ситуации.
Для п.2 интерфейс используется как граница между "вообще решением" и "решением для конкретной ситуации". Например задача — импортировать юзеров из CSV файла — в SQL базу.
interface UserHandler {
void handleUser(User user);
}
class UserCsvReader {
void readAllUsers(UserHandler userHandler) {
...
}
}
class BatchInserter<TRow> {
BatchInserter(String sql, int batchSize) {...}
void insert(TRow row) {
if (batch.size < batchSize) {
batch.add(row);
} else {
connection.batchUpdate(sql, batch);
batch.clear();
}
}
}
class BatchInsertingUserHandler implements UserHandler {
BatchInsertingUserHandler(BatchInserter<UserRow> batchInserter) {}
void handleUser(User user) {
UserRow r = makeRowFromUser(user);
batchInserter.insert(r);
}
}
BatchInserter<UserRow> batchInserter = new BatchInserter("insert into Users(...)");
BatchInsertingUserHandler userHandler = new BatchInsertingUserHandler(batchInserter);
UserCsvReader reader = new UsersCsvReader();
reader.readAllUsers(userHandler);
Здесь интерфейс UserHandler используется чтобы отрезать "читание users CSV" от "писания в БД". Интерфейс тут позволяет показать, что вот этот код он конкретно про читание. Он используется при импорте юзеров, но это не сам импорт, а один из инструментов, которые используются импортом.
Если интерфейс выкинуть и оставить только сам BatchInsertingUserHandler, тут возникает много неясностей по поводу как кого переименовать, чтобы не получилось, что холодильник знает о существовании духовки, потому что они оба на кухне.