Adapter Pattern

Sometimes we need to change the interface of a class in order to be usable for a client. This could happen due to various reasons such as the existing interface may be too detailed, or it may lack details or the terminology used by the interface may be different from what the client is looking for.

The Adapter pattern suggests defining a wrapper class around the object with the incompatible interface. This wrapper object is referred as an adapter and the object it wraps is referred to as an adaptee. The adapter provides the required interface expected by the client. The implementation of the adapter interface converts client requests into calls to the adaptee class interface.

There are two types of adapters, Class Adapter and Object Adapter. Class Adapter is based on inheritance and inherits the adaptee class. Object Adapter works based on composition and has a reference to the adaptee object. Both should implement (does not mean necessarily interface implementation) the interface which the client expects.

Class vs. Object Adapter:

adapter.jpeg

Consequences:
Class adapter only adapts one class but object adapter can adapt an interface adaptee with all its subclasses.

public class Client {
    Adapter adapter;    
    adapter.doWork(some_interface);
}
 
//client actually wants to call action(some_other_interface) but due to any reason it can not.
public class Adaptee{
    Public SomeWork action(some_other_interface){
    }
}
 
//Composition Adapter - object adapter
public class Adapter{
    Adaptee adaptee;
    public SomeWork doWork(some_interface){
        ...
        adaptee.action(some_other_interface);        
        ...
    }
}
 
//Inheritance Adapter - class adapter
public class Adapter extends Adaptee{
    ...    
    public SomeWork doWork(some_interface){
        ...
        adaptee.action(some_other_interface);        
        ...
    }
}

Look at this variation:

public class Client {
    Adapter adapter;    
    adapter.doWork(some_interface);
}
 
public interface Adaptee{
    Public SomeWork action(some_other_interface);
}
 
public interface Adapter extends Adaptee{
    Public SomeWork doWork(some_interface);
}
 
public class AdapterImpl implements Adapter{
 
    Public SomeWork doWork(some_interface){    //client can call
        ...
        action(some_other_interface);
        ...
    }
 
    Public SomeWork action(some_other_interface){    //client can not call
    ...
    }
}

Now a more real example. Notice that DialValidator could be an interface.

public interface ProductValidator {
    public boolean isValid(String productName,Integer productNumber);
}
 
public class AdslValidator implements ProductValidator {
    public boolean isValid(String productName, Integer productNumber) {
        return false;
    }
}
public class Client {
    ProductValidator validator;
 
    public boolean testAdslValidation(){
        validator.isValid("some adsl", 123);
        return false;
    }
}
 
public class DialValidator {
    public boolean isValid(String productName) { //a different interface
        return false;
    }
}
 
public class DialAdapter extends DialValidator implements ProductValidator {
    public boolean isValid(String productName, Integer productNumber) {
        return isValid(productName);//adapting the interface
    }
}
 
public class Client {
    ProductValidator validator;
 
    public boolean testDialValidation(){
        validator.isValid("some adsl", 123);
        return false;
    }
}

Related Patterns:
Adapter is in some aspects similar and related to proxy, decorator and bridge.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License