Для того, чтобы отделить мух от котлет.
Представь, что у тебя условно есть 3 отдела. И все они между собой очень тесно связаны. Ну не могут работать друг без друга и все тут. В итоге захотел поменять что-то во втором отделе, будь добр поменяй и в остальных двух, ибо они от него напрямую зависят.
Первое, что приходит в голову - создание абстрактных интерфейсов, через которые все взаимодействие и происходит. Ок, создали. Но абстрактные интерфейсы делать ничего не могут, на то они абстрактные. Значит где-то нужно явно создавать реализацию для этой абстракции. Становится вопрос где это делать. Создавать внутри одного класса - экземпляры другого, это уже тоже сильная связанность между ними. Для этого и придумали ящик, где будут храниться все соответствия между интерфейсами и реализациями. Захотел получить реализацию такого-то интерфейса, попросил ответственного менеджера, он сам заглянул в свой ящик и вытащил то, что тебе требуется. И назвали это все Контейнер Зависимостей (Dependency Container). То есть это конкретный инструмент для создания слабых связей между модулями.
Ну а слабая связанность модулей и абстракции между ними дают всякие полезные фишки по типу быстрого переключения между реализациями (например реальное/тестовое окружение), позволяет проще рефакторить отдельные модули и так далее.