Ответ
Абстрактный сервис, будучи шаблоном для конкретных реализаций, обычно зависит от интерфейсов (абстракций), а не от конкретных классов. Это следует принципу инверсии зависимостей (DIP). В моих проектах на Symfony/Laravel такие зависимости включали:
1. Репозитории (Data Access Layer) Абстрактный сервис получает интерфейсы репозиториев для доступа к данным, скрывая детали реализации (Doctrine ORM, Eloquent, прямой PDO).
abstract class AbstractOrderService
{
protected OrderRepositoryInterface $orderRepository;
protected UserRepositoryInterface $userRepository;
public function __construct(
OrderRepositoryInterface $orderRepository,
UserRepositoryInterface $userRepository
) {
$this->orderRepository = $orderRepository;
$this->userRepository = $userRepository;
}
}
2. Другие сервисы (Domain Services) Зависимость от интерфейсов других сервисов предметной области для разделения ответственности.
abstract class AbstractPaymentService
{
protected NotificationServiceInterface $notifier;
protected LoggerInterface $logger;
// ...
}
3. Объекты передачи данных (DTO) и спецификации Сервис может быть параметризован классами DTO для ввода/вывода или интерфейсами спецификаций (Specification pattern) для инкапсуляции бизнес-правил.
4. Инфраструктурные сервисы
- Логгер (PSR-3
LoggerInterface): Для записи событий и ошибок. - Отправщик событий (
EventDispatcherInterface): Для декoupling логики через события домена. - Кеш (PSR-6
CacheItemPoolInterfaceили PSR-16CacheInterface): Для оптимизации. - Валидатор: Часто через интерфейс, например,
SymfonyComponentValidatorValidatorValidatorInterface.
5. Фабрики Интерфейсы фабрик для создания сложных объектов, если это входит в ответственность сервиса.
Ключевые принципы при проектировании:
- Внедрение зависимостей через конструктор (Constructor Injection): Это делает зависимости явными и сервис сразу готов к работе.
- Зависимость от абстракций: Это позволяет легко подменять реализации (например, мокировать в тестах) и соблюдать Open/Closed Principle.
- Минимизация зависимостей: Абстрактный сервис не должен превращаться в "Божественный объект". Если зависимостей слишком много — возможно, сервис нарушает Single Responsibility Principle.
В итоге, абстрактный сервис определяет общий контракт и базовую логику для наследников, а его зависимости задают границы его взаимодействия с другими слоями приложения.