Каждый раз, когда мне необходимо написать некоторый сервис, я сталкиваюсь со следующим вопросом:
Предположим нужен сервис, который осуществляет оповещения пользователей. Оповещать можно, например, в Slack, по SMS и в Telegram. Вижу 2 варианта решения
1. Создать некоторый абстрактный класс Notifier с абстрактным методом notify,
и для каждого сервиса (Slack, SMS, Telegram) создать дочерние классы, наследующие Notifier (SlackNotifier, SMSNotifier, TelegramNotifier), в которых по своему реализовать метод nofity.
После чего в контроллер из DI контейнера получать необходимую реализацию, в зависимости от конфигурации.
2. Создать вполне конкретный Notifier, а в нём как зависимость инстанцировать SlackDriver, SMSDriver или TelegramDriver реализующие общий интерфейс с методом notify, а в методе Notifier::notify() делигировать выполнение инстанцированному драйверу:
public function notify() {
$this->driver->notify();
}
И вот я не пойму, какой подход лучше и по каким критериям? В случае с конкретным Notifier контроллер будет зависеть не от абстракции (это плохо?). В первом случае мы можем подменить сам Notifier, в другом - его драйвер. Я так понимаю это тот самый вопрос: "наследование или композиция"? Помогите разобраться.