Хорошим примером IoC является макетирование базы данных. Пока вы пишете приложение, вам может понадобиться сохранить объекты для поиска или использования в более поздний момент времени. Ну, чтобы абстрагировать базу данных, вы создаете интерфейс с помощью метода, подобного этому:
Interface DbSaver
+void save( MyObject myObject )
+MyObject load( String id )
Без IoC у вас было бы что-то вроде этого:
DbSaver saver = new DefaultDbSaver();
или вы просто определили бы реализацию и получили бы доступ к ней как к одиночке (которая изначально кажется подходящей для объекта манипулирования базой данных):
MyDbSaver saver = MyDbSaver.getInstance();
С IoC вы можете переключать реализацию DbSaver, даже не перекомпилируя ваше приложение (по крайней мере, Spring предоставляет это). То есть, не меняя код, вы можете использовать одну реализацию поверх другой. С объектами доступа к базе данных наиболее распространенным является создание реализации по умолчанию, которая хранит все в памяти. Когда вы дорабатываете дизайн, структуру или технологию своей базы данных, вы можете продолжать создавать приложение, не беспокоясь о том, как данные будут сохраняться. Вы просто работаете в интерфейсе.
Таким образом, бизнес-объекты не связаны с интеграцией базы данных, что дает огромное преимущество, позволяя разрабатывать обе части параллельно.