Rules of Thumb?

Every dependency in the design should target an interface or an abstract class. No dependency should target a concrete class.

Factories and Abstract Factories can be used as dependency frameworks, but there are specialized frameworks for that such as Spring IOC (Inversion of Control Container).

Benefits

Loose Coupling - don't ask for dependency it will be provided to you by the framework. This has been very well implemented in Spring framework, the beauty of this design principle is that any class which is injected by DI framework is easy to test with the mock object and easier to maintain because object creation code is centralized in the framework and client code is not littered with that.

Dependency Inversion Principle Example

Let's take an example of a simple Customer Management example. If you see the source code, we are connecting to MySQL and performing CRUD operations for the customer. The MySQLDatasourceclass object is created using new keyword in CustomerDaoImpl.

Here CustomerDaoImpl is hardly depended on MySQLDatasource so if we want to switch MySQL to Oracle database then we need to change CustomerDaoImpl for Oracle database connection.

Let's see how this design principle provides the solution to avoid hard dependencies.

Note that from the above code example, CustomerDaoImpl class depends on the DataSource interface, not the concrete class. Now due to abstraction Client can change implementation at any time. For example, now client using MySQL and in future client might interested use Oracle then simply provide the Oracle implementation as Constructor to CustomerDaoImpl.