Есть много причин, почему глобалы злы в ООП.
Если число или размер объектов, нуждающихся в совместном использовании, слишком велик, чтобы их можно было эффективно передать в параметрах функции, обычно все рекомендуют внедрение зависимостей вместо глобального объекта.
Однако в случае, когда почти каждый должен знать об определенной структуре данных, почему внедрение зависимостей лучше, чем глобальный объект?
Пример (упрощенный, чтобы показать суть в целом, не углубляясь в конкретное приложение)
Существует ряд виртуальных транспортных средств, которые имеют огромное количество свойств и состояний, от типа, имени, цвета, скорости, положения и т. Д. Ряд пользователей может управлять ими дистанционно, а также огромное количество событий (как инициируется и автоматически) может изменить многие их состояния или свойства.
Наивным решением было бы просто создать из них глобальный контейнер, например
vector<Vehicle> vehicles;
к которому можно получить доступ откуда угодно.
Более дружественным к ООП решением было бы иметь контейнер, являющийся членом класса, который обрабатывает основной цикл событий, и создавать его экземпляры в своем конструкторе. Каждый класс, который нуждается в нем и является членом основного потока, получит доступ к контейнеру через указатель в своем конструкторе. Например, если внешнее сообщение поступает через сетевое соединение, класс (по одному на каждое соединение), обрабатывающий синтаксический анализ, вступит во владение, и парсер получит доступ к контейнеру через указатель или ссылку. Теперь, если проанализированное сообщение приводит к изменению элемента контейнера или требует каких-либо данных из него для выполнения действия, оно может обрабатываться без необходимости бросать тысячи переменных через сигналы и слоты (или, что еще хуже, сохранение их в парсере для последующего извлечения тем, кто вызвал парсер). Конечно, все классы, которые получают доступ к контейнеру через внедрение зависимостей, являются частью одного и того же потока. Различные потоки не будут напрямую обращаться к нему, но будут выполнять свою работу, а затем отправлять сигналы в основной поток, а слоты в основном потоке будут обновлять контейнер.
Однако, если большинство классов получат доступ к контейнеру, что действительно отличает его от глобального? Если такому классу нужны данные в контейнере, не является ли «путь внедрения зависимостей» просто замаскированным глобальным?
Одним из ответов будет безопасность потоков: даже если я позабочусь о том, чтобы не злоупотреблять глобальным контейнером, возможно, другой разработчик в будущем, под давлением близкого срока, все же будет использовать глобальный контейнер в другом потоке, не заботясь обо всех случаи столкновения. Однако даже в случае внедрения зависимости можно указать указатель на кого-то, работающего в другом потоке, что приводит к тем же проблемам.