CarMaintenanceReminder: Service Locator и зависимости

Основные проблемы выбранной структуры решения:

Короткий ответ

Что ответить на собеседовании

Основные проблемы выбранной структуры решения:

Подробный разбор

Ответ с пояснениями

Условие

В чём основная проблема выбранной структуры решения

  • Жесткая инициализация финал-полей
  • Структура не гарантирует уникальности сервисов в кеше
  • Поиск сервисов усложняет тестирование
  • Нет шаблона использования. Стратегия гибкости.
  • Сервис-локатор затрудняет отладку

Код:

public class CarMaintenanceReminder { private final ServiceLocator serviceLocator; private final ReminderCache reminderCache;

public CarMaintenanceReminder() {
    this.serviceLocator = new ServiceLocator();
    this.reminderCache = new ReminderCache();
}

public Reminder getOilChangeReminder(String carId) {
    Reminder reminder = reminderCache.getReminder(carId);
    if (reminder == null) {
        reminder = serviceLocator.getService(ReminderService.class).createOilChangeReminder(carId);
        reminderCache.addReminder(reminder);
    }
    return reminder;
}

}

class ServiceLocator { public <T> T getService(Class<T> serviceClass) { return serviceClass.cast(generateService(serviceClass)); }

private Object generateService(Class<?> serviceClass) {
    if (serviceClass == ReminderService.class) {
        return new ReminderService();
    }
    return null;
}

}

class Reminder { private final String carId; public Reminder(String carId) { this.carId = carId; } }

class ReminderService { public Reminder createOilChangeReminder(String carId) { return new Reminder(carId); } }

class ReminderCache { private final Map<String, Reminder> cache;

public ReminderCache() {
    this.cache = new HashMap<>();
}

public Reminder getReminder(String carId) {
    return cache.get(carId);
}

public void addReminder(Reminder reminder) {
    cache.put(reminder.getCarId(), reminder);
}

}

Ответ

Основные проблемы выбранной структуры решения:

  • Жёсткая инициализация финальных полей: В классе CarMaintenanceReminder сервисы создаются внутри конструктора напрямую (new ServiceLocator(), new ReminderCache()), что затрудняет замену или мокирование этих зависимостей при тестировании и снижает гибкость.
  • Структура не гарантирует уникальности сервисов в кеше: ServiceLocator каждый раз создаёт новый экземпляр сервиса (new ReminderService()), вместо того чтобы кэшировать или использовать синглтоны. Это может привести к избыточному созданию объектов и проблемам с состоянием.
  • Поиск сервисов усложняет тестирование: Использование паттерна сервис-локатора скрывает зависимости класса, что усложняет понимание и тестирование, так как зависимости неявны и не передаются явно.
  • Нет шаблона использования, стратегия гибкости: Отсутствие паттернов внедрения зависимостей (Dependency Injection) или стратегий конфигурации снижает гибкость и расширяемость.
  • Сервис-локатор затрудняет отладку: Из-за динамического получения сервисов через ServiceLocator сложнее отследить, какой именно сервис используется, что усложняет отладку и сопровождение.

Рекомендуется использовать внедрение зависимостей через конструктор, чтобы явно передавать необходимые сервисы, а также применять паттерны, обеспечивающие управление жизненным циклом сервисов и их уникальность. Например:

public class CarMaintenanceReminder {
    private final ReminderService reminderService;
    private final ReminderCache reminderCache;

    public CarMaintenanceReminder(ReminderService reminderService, ReminderCache reminderCache) {
        this.reminderService = reminderService;
        this.reminderCache = reminderCache;
    }

    public Reminder getOilChangeReminder(String carId) {
        Reminder reminder = reminderCache.getReminder(carId);
        if (reminder == null) {
            reminder = reminderService.createOilChangeReminder(carId);
            reminderCache.addReminder(reminder);
        }
        return reminder;
    }
}

Такой подход улучшает тестируемость, читаемость и поддержку кода.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее