Many large projects as they grow inevitably face the following list of problems:
Concentration of motley logic in one place, blurred responsibility, classes of several thousand lines. Familiar symptoms right?
To combat the high complexity of logic, there is a good old divide-and-conquer technique. As a rule, complex things consist of a subset of simple ones that is is much easier to understand.
Changed or added logic in one part of the application, but broke in completely different one (maybe even completely unrelated at first glance).
Classes interact very closely with each other and each of them strictly relies on the implementation of its neighbors.
There are many technical articles on this subject, but let's have some fun and try to dilute the explanation with exaggerated analogies.
Meet, ladies and gentlemen, the very abstract Peter:
As you can see from the illustration, Peter is a pianist with a great sense of humor. Pretty good guy, huh?
However, Peter does not have enough female attention for complete happiness. So he decides to find a girl.
Peter wanders around clubs and pubs, attends theme parties, tries to seduce female colleagues. But all to no avail... The perfect, the NECESSARY girl has not yet been found...
Finally, tired and sad Peter decides to abandon these attempts and focus on his work.
But the dream of great love nevertheless glimmers in him and he decides to APPEAL to a specialized dating service to shift burden of searching the second half for SPECIALLY TRAINED people.
When addressing, Peter fills out a form in which he describes in detail the girl of his dreams.
It turns out that Peter is not only a wonderful musician, but also a lucky one.
Because the perfect candidate was quickly found in the agency database. In accordance with all the wishes of Peter.
The agency sends the girl’s contacts to our musician. Well, then magic of love, romance and "they lived happily ever after."
Well, now it's time to take off the masks and move on to the realities of development in terms of Dependency Injection:
Client - our Peter, a consumer who needed some value
Interface - the form that Peter filled out
Injector - a dating agency that picked up a girl for Peter
Service - the beloved of Peter, whom he has sought for so long
IoC(inversion of control) container - the agency's database
Please note that in the first case, Peter acted ACTIVELY and independently tried to find his Service, but at the same time he completely forgot about his main activity.
He later delegated responsibility to the agency and spoke in a PASSIVE position.
All he did was declare his needs(INTERFACE) and leave contact details for communication.
So the special service(AGENCY) easily fulfilled its only responsibility - to find a couple for Peter.
This pattern allows to separate and isolate clients from dependency implementation. All it needs is an interface. Clients can be concentrated on their own activities, because all dirty work would be done automatically by special INJECTOR service beyond the scope of a CLIENT.
Additionally, an isolated class is very easy to test with unit tests, because under the mask of the interface you can enclose MOCK or FAKE.