The difference is that in the consumer class you will work with the object at the level of abstractions and be able to substitute any implementation of the abstract interface. I will give an example: You have an interface that provides a certain set of operations. Today, the customer wants the GetSomeInfo () method of implementing this interface to refer to the local database, as well as to the web service in the future. At the initial stage, you write the implementation of MyBDInterfaceImplementation, which has GetSomeInfo () to the database. The consumer class simply knows about the interface that it owns the GetSomeInfo method and calls it. Then you implement another class that implements this interface and the GetSomeInfo () method in this case accesses the web service. As a result, in the consumer class you do not need to change anything, only in the place where the constructor of this class is called to transfer an object of another type to it. Thus, in practice, the user of your application chooses to use a local database — you transfer the first implementation of the interface to the consumer class constructor if the user selects a web service — in a similar way, substitute the implementation with access via the web service. The next plus is testability. First, it is easy to write using TDD, User Stories, and so on. Secondly, it is easy to test using mocks, dummy implementations, and so on.
Fowler's article on IoC will also be useful. Rob Martin's books on agil-development and clean code.
I hope the answer to the question helped to understand.