Adapter Design Pattern


Intent

Convert the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

Also known as

Wrapper

Explanation

Real world example

Consider that you have some pictures in your memory card and you need to transfer them to your computer. In order to transfer them you need some kind of adapter that is compatible with your computer ports so that you can attach memory card to your computer. In this case card reader is an adapter. Another example would be the famous power adapter; a three legged plug can't be connected to a two pronged outlet, it needs to use a power adapter that makes it compatible with the two pronged outlet. Yet another example would be a translator translating words spoken by one person to another

In plain words

Adapter pattern lets you wrap an otherwise incompatible object in an adapter to make it compatible with another class.

Wikipedia says

In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.

Structure

Participants

1. Target
  • defines the domain-specific interface that Client uses.
2. Client
  • collaborates with objects conforming to the Target interface.
3. Adaptee
  • defines an existing interface that needs adapting. 
4. Adapter
  • adapts the interface of Adaptee to the Target interface.

Collaborations

  • Clients call operations on an Adapter instance. In turn, the adapter callsAdaptee operations that carry out the request. 

Example

  • The client makes a request to the adapter by calling a method on it using the target interface.
  • The adapter translate the request into one or more calls on adaptee using adaptee interface.
  • The client recieves the results of the client and never knows there is an adapter doing translation.

Source code

Step 1 : Create a CreditCard interface (Target interface).
public interface CreditCard {  
    public void giveBankDetails();  
    public String getCreditCard();  
}// End of the CreditCard interface.  
Step 2 : Create a BankDetails class (Adaptee class).
/ This is the adapter class.  
public class BankDetails{  
    private String bankName;  
    private String accHolderName;  
    private long accNumber;  
      
    public String getBankName() {  
        return bankName;  
    }  
    public void setBankName(String bankName) {  
        this.bankName = bankName;  
    }  
    public String getAccHolderName() {  
        return accHolderName;  
    }  
    public void setAccHolderName(String accHolderName) {  
        this.accHolderName = accHolderName;  
    }  
    public long getAccNumber() {  
        return accNumber;  
    }  
    public void setAccNumber(long accNumber) {  
        this.accNumber = accNumber;  
    }  
}// End of the BankDetails class.
Step 3 : Create a BankCustomer class (Adapter class).
// This is the adapter class  
  
import java.io.BufferedReader;  
import java.io.InputStreamReader;  
public class BankCustomer extends BankDetails implements CreditCard {  
 public void giveBankDetails(){  
  try{  
   BufferedReader br=new BufferedReader(new InputStreamReader(System.in));  
      
   System.out.print("Enter the account holder name :");  
   String customername=br.readLine();  
   System.out.print("\n");  
      
   System.out.print("Enter the account number:");  
   long accno=Long.parseLong(br.readLine());  
   System.out.print("\n");  
      
   System.out.print("Enter the bank name :");  
   String bankname=br.readLine();  
      
   setAccHolderName(customername);  
   setAccNumber(accno);  
   setBankName(bankname);  
   }catch(Exception e){  
        e.printStackTrace();  
   }  
  }  
  @Override  
  public String getCreditCard() {  
   long accno=getAccNumber();  
   String accholdername=getAccHolderName();  
   String bname=getBankName();  
          
   return ("The Account number "+accno+" of "+accholdername+" in "+bname+ "  
                        bank is valid and authenticated for issuing the credit card. ");  
  }  
}//End of the BankCustomer class.
Step 4 : Create a AdapterPatternDemo class (client class).
/This is the client class.  
public class AdapterPatternDemo {  
 public static void main(String args[]){  
  CreditCard targetInterface=new BankCustomer();  
  targetInterface.giveBankDetails();  
  System.out.print(targetInterface.getCreditCard());  
 }   
}//End of the BankCustomer class.  
Output :
Enter the account holder name :Sonoo Jaiswal  
  
Enter the account number:10001  
  
Enter the bank name :State Bank of India  
  
The Account number 10001 of Sonoo Jaiswal in State Bank of India bank is valid   
and authenticated for issuing the credit card. 

Applicability

Use the Adapter pattern when

  • you want to use an existing class, and its interface does not match the one you need
  • you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces
  • you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class.
  • most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.

Consequences

  • Class and object adapters have different trade-offs. A class adapter adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter won’t work when we want to adapt a class and all its subclasses.
  • let’s Adapter override some of Adaptee’s behavior, since Adapter is a subclass of Adaptee.
  • introduces only one object, and no additional pointer indirection is needed to get to the adaptee.
An object adapter
  • let’s a single Adapter work with many Adaptees—that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once.
  • makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself.

Real world examples

Comments