Ответ
Подмена реализации (класса) — ключевой принцип гибкого и тестируемого дизайна. Основные случаи:
-
Тестирование (Изоляция зависимостей): Замена реальных, медленных или недетерминированных компонентов на заглушки (stubs) или моки (mocks).
// Без подмены: тест зависит от реальной БД // С подменой: используем mock-объект @Test void testService() { PaymentGateway mockGateway = mock(PaymentGateway.class); when(mockGateway.process(any())).thenReturn(SUCCESS); OrderService service = new OrderService(mockGateway); // Внедряем mock // Тестируем логику service, не вызывая реальный платёжный шлюз } -
Смена реализации (Следование интерфейсам): Позволяет менять поведение системы, не изменяя код, который от него зависит (Принцип инверсии зависимостей - DIP).
interface DataRepository { /* ... */ } class SqlRepository implements DataRepository { /* ... */ } class InMemoryRepository implements DataRepository { /* ... */ } // Конфигурация решает, какую реализацию использовать DataRepository repo = new InMemoryRepository(); // Для тестов DataRepository repo = new SqlRepository(); // Для продакшена -
Расширение функциональности (Паттерн Декоратор): Динамическое добавление новой ответственности к объекту.
interface DataSource { InputStream getData(); } class BasicDataSource implements DataSource { /* ... */ } // Декоратор добавляет логирование class LoggingDataSource implements DataSource { private DataSource wrapped; public LoggingDataSource(DataSource ds) { this.wrapped = ds; } @Override public InputStream getData() { log("Requesting data..."); // Добавленное поведение return wrapped.getData(); // Оригинальное поведение } } -
Адаптация интерфейсов (Паттерн Адаптер): Позволяет объектам с несовместимыми интерфейсами работать вместе.
Ключевой принцип: Программирование на уровне интерфейсов/абстракций, а не конкретных реализаций.