Сравнение методов привязки объектов в сервис-контейнере Laravel
| Метод | bind() |
singleton() |
scoped() |
instance() |
|---|---|---|---|---|
| Описание | Создает новый экземпляр каждый раз при разрешении. | Создает только один экземпляр и возвращает тот же экземпляр в последующих запросах. | Создает только один экземпляр в рамках каждого жизненного цикла запроса/задачи; он очищается после завершения запроса. | Привязывает существующий экземпляр к контейнеру и возвращает этот экземпляр каждый раз при разрешении. |
| Плюсы | - Свежий экземпляр для каждого запроса, нет проблем с общим состоянием - Чистое использование памяти - Подходит для логики, требующей независимого состояния - Может предоставлять уникальную конфигурацию для каждого запроса |
- Экономит системные ресурсы, создавая экземпляр только один раз - Обеспечивает согласованность состояния - Подходит для совместного использования конфигурации и ресурсов - Лучшая производительность при высокой конкурентности |
- Баланс использования памяти и общего состояния - Совместное использование состояния внутри запроса, но изоляция между запросами - Подходит для сценариев веб-запросов |
- Полный контроль над временем создания экземпляра - Можно предварительно настроить состояние экземпляра - Подходит для сервисов, требующих определенной конфигурации |
| Минусы | - Требует больше системных ресурсов для повторного создания экземпляров - Может повлиять на производительность при высокой конкурентности - Не подходит для сценариев, требующих общего состояния - Может вызвать проблемы с производительностью, так как каждый раз создается новый экземпляр. |
- Общее состояние может привести к трудноотслеживаемым ошибкам - Не подходит для сценариев, требующих независимого состояния - Использование памяти сохраняется до завершения программы - Тестирование требует особого внимания к сбросу состояния - Если экземпляр содержит состояние, это может вызвать неожиданное поведение. |
- Может вызвать проблемы в длительных задачах - Требует понимания жизненного цикла запроса - Не подходит для команд CLI |
- Менее гибкий - Нельзя динамически настраивать конфигурацию экземпляра - Может занимать память при запуске - Не подходит для случаев, требующих ленивой загрузки или нескольких экземпляров. |
| Сценарий использования | Для краткосрочных сервисов или классов, требующих независимого состояния. | Для глобально общих сервисов, таких как логгеры или менеджеры конфигурации. | Для сервисов, которым необходимо поддерживать состояние внутри запроса, но не между запросами, таких как соединения с базой данных. | Когда у вас уже есть экземпляр и вы хотите использовать его повторно, например, общий объект конфигурации. |
| Пример | Когда у вас есть класс Product и вы хотите создавать новый экземпляр Product каждый раз, когда запрашиваются разные данные о продукте. |
Когда у вас есть класс Logger и вы хотите, чтобы все операции записи логов использовали один и тот же экземпляр для поддержания согласованности. |
Когда у вас есть класс ShoppingCart и вам нужно разделить состояние корзины покупок в рамках одного запроса. |
Когда у вас есть класс DatabaseConfig и вам нужно установить параметры соединения при запуске приложения. |
Примеры
Использование bind()
$this->app->bind('Product', function () {
return new Product();
});
Каждый раз при вызове app('Product') возвращается новый экземпляр Product.
Использование singleton()
$this->app->singleton('Logger', function () {
return new Logger();
});
Каждый раз при вызове app('Logger') возвращается тот же экземпляр Logger.
Использование scoped()
$this->app->scoped(Transistor::class, function (Application $app) {
return new Transistor($app->make(PodcastParser::class));
});
Разделяет один и тот же экземпляр в рамках одного жизненного цикла запроса; разные запросы будут создавать новые экземпляры.
Использование instance()
$service = new Transistor(new PodcastParser);
$this->app->instance(Transistor::class, $service);
Привязывает существующий экземпляр напрямую к контейнеру.
Резюме
Laravel в настоящее время может применяться во многих различных типах сценариев, таких как веб-запросы, команды CLI, задачи очереди, команды консоли и т. д.
Поэтому при выборе метода привязки вам необходимо учитывать потребности сервиса в различных сценариях и то, нужно ли вам делиться состоянием или конфигурацией.