In Simple words,
Class Adapter uses Subclassing and Object Adapter uses delegation by using composition.
Example:
class MyExistingServiceClass {
public void show() {
System.out.println("Inside Service method show()");
}
}
interface ClientInterface {
void display();
}
class MyNewClassAdapter extends MyExistingServiceClass implements ClientInterface {
void display() {
show();
}
}
Above is an example of Class Adapter. We have adapted MyExistingServiceClass to ClientInterface by calling existing show() method from inside implementation of display().
To convert this to object adapter, the code will be like :
class MyNewObjectAdapter implements ClientInterface {
MyExistingServiceClass existingClassObject;
void display() {
existingClassObject.show();
}
}
Now when to use Object adapter in place of Class Adatper,
When there is no way to subclass the class which is going to be adapted as per client's interface. Examples like, when MyExistingServiceClass is declared as final.
When client expects a contract which is not an inteface but an abstract class implementation. In this case, we have no other way than to subclass the client's expected class and as we can't subclass more than one class, there is no other way than using the class to be adapted as a composition.
abstract class AbstractClientClass {
abstract void display();
}
class MyNewObjectAdapter extends AbstractClientClass {
MyExistingServiceClass existingClassObject;
void display() {
existingClassObject.show();
}
}
When you need to adapt more than one object. Such case are when you are not directly working with object to be adapted. A good example here would be JTable class in javax.swing. This class creates a GUI (graphical user interface) table component filled with the information that your adapter feeds to it. To display data from your domain, JTable provides constructors that accept an instance of the TableModel
defined in javax.swing.table. JDK provides an existing abstract implementation of TableModel with AbstractTableModel.
class MyTableModel extends AbstractTableModel {
MyDomainObject[] existingDomainObjects[];
public int getColumnCount() {
return 4;
}
public int getRowCount() {
return existingDomainObjects.length();
}
public MyDomainObject getValueAt(int i) {
return existingDomainObjects[i];
}
}
Here, we have adapted MyDomainObject in order to be used with AbstractTableModel.