I am not a specialist like others, but I will attempt to describe DIP in terms of concept. Program to an interface is at the heart of DIP, which means that your high-level classes will rely on abstraction, and your low-level classes will rely on abstraction as well. as an example
Let's imagine you define a PhoneVendor abstraction, which can be anything from Samsung to Apple to Nokia. Sorry for the code; I haven't written Java in a long time, so it may contain grammatical errors, but the concept remains the same.
public abstract class PhoneVendor {
/**
* Abstract method that returns a list of phone types that each vendor creates.
*/
public abstract Vector getPhones(){ }
}
public class Samsung extends PhoneVendor{
public Vector getPhones(){ // return a list of phones it manufactures... }
}
public class PhoneFinder{
private PhoneVendor vendor;
public PhoneFinder(PhoneVendor vendor){ this.vendor = vendor;}
/**
*for example just return a concatnated string of phones
*/
public string getPhoneTypes(){
Vector ListOfPhones = PhoneVendor.getPhones();
return ListOfPhones;
}
}
As you can see, the PhoneFinder class is based on the abstraction rather than the PhoneVendor implementation. And the Abstraction is divorced from the high-level classes that use it in your essential classes. This makes the design extremely adaptable, as introducing new Low level classes will not break any previously created code because PhoneFinder is based on abstraction rather than implementation.