Basically, the main idea of DIP is:
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
As you can see, it says should and not must. It does not forbid you from doing anything.
If your classes composite of / aggregate to
other specific classes
(not interfaces / abstract classes
), it is fine! Your code will still compile and run, no warnings will be displayed telling you: "hey, you are violating DIP". So I think the answer to your question is: No, it doesn't.
Imagine your system is composed of a thousand classes, you can just apply DIP to 2 classes and have one of them depends on the 3rd specific class (not interfaces / abstract classes
). As long as your problem is solved, nothing matters. So try to keep your solution short & simple -> easy to understand. Trust me you will find it valuable 1 month after when you look back at your solution.
DIP is a guideline which tells you what to do when you face a specific set of problems in order to solve them. It is not a magical guideline, it comes at a cost: complexity. The more you apply DIP the more complex your system will be. So use it wisely. To further support this point, I recommend you to take a look at this reference (taken from Head First: Design Patterns
book). Access this link (it is a PDF file) and at the top bar navigate to page 635 / 681
. Or if you are lazy enough, just read the below quote:
Your Mind on Patterns
The Beginner uses patterns everywhere. This is good: the beginner gets lots of experience with and practice using patterns. The beginner
also thinks, “The more patterns I use, the better the design.” The
beginner will learn this is not so, that all designs should be as
simple as possible. Complexity and patterns should only be used where
they are needed for practical extensibility.
As learning progresses, the Intermediate mind starts to see where patterns are needed and where they aren’t. The intermediate mind
still tries to fit too many square patterns into round holes, but also
begins to see that patterns can be adapted to fit situations where the
canonical pattern doesn’t fit.
The Zen mind is able to see patterns where they fit naturally. The Zen mind is not obsessed with using patterns; rather it looks for
simple solutions that best solve the problem. The Zen mind thinks in
terms of the object principles and their trade-offs. When a need for a
pattern naturally arises, the Zen mind applies it knowing well that it
may require adaptation. The Zen mind also sees relationships to
similar patterns and understands the subtleties of differences in the
intent of related patterns. The Zen mind is also a Beginner mind — it
doesn’t let all that pattern knowledge overly influence design
decisions.
Finally, I will point you to a Gang of Four design pattern that make use of DIP: Strategy
Example problem: A Character
can use 3 types of weapon: Hand
, Sword
, & Gun
. He (Character
) can swap his current weapon whenever he wants.
Analysis: This is a very typical problem. The tricky part is how to handle weapon swapping at run-time.
Candidate solution with Strategy: (just a sketchup):

weapon = new Hand();
weapon.Attack(); // Implementation of Hand class
weapon = new Sword();
weapon.Attack(); // Implementation of Sword class
weapon = new Gun();
weapon.Attack(); // Implementation of Gun class
Other design patterns & frameworks that make use of DIP: