Adapter design pattern in Java – with examples

Every day millions of lines of code is written. Most of the code is rewritten. Many a times there is a small change in requirement and old code doesn’t fit. What if we adapt the code so that it becomes reusable? Adapter design pattern in java helps to reuse the existing code even if it is incompatible. You can learn and use this approach while developing any application.

With real life and software examples we will see how to reuse the things even if they are not compatible with each other. You can leave a comment on how you feel about the post or if you have already used this pattern you can share the experience with us.

What is adapter design pattern?

Adapter design pattern in java is a structural design pattern. It provides solution for helping incompatible things to communicate with each other. It works as an inter-mediator who takes output from one client and gives it to other after converting in the expected format. Adapter pattern is also known as wrapper. [wiki]

For understanding adapter design pattern, we can look at the real world adapters or inter-mediators. Like, consider we have two water pipes of different sizes, and we want to connect them. We can not connect directly. So what can we do in such a case? As shown in the image below, we can use reducer. Here the reducer acts as an inter-mediator helping us to join the two pipes.

Example of Adapter design pattern

Similarly, in case of software development there are so many cases where we need inter-mediators. In such cases Adapter pattern in java is used.

import java.util.Scanner;
public class Test{

     public static void main(String []args){
	String a = new Scanner(System.in).nextLine();
        process(a);  
     }

    public static void process(integer a){
        System.out.println("Square of "+a +" is "+ (a*a));
    }
}

Output:

error: incompatible types: String cannot be converted to int

Confussed face

As you can see in above code we have string type variable. Therefore, even if we want to call process() function we can not. Because it takes integer parameter as input. Hence, we need to create another method which can process a string or need to find way to convert String into integer format. The method which will do this processing is the Adapter method.

Adapter design pattern structure

Flow diagram of Adapter design pattern

The figure above shows the basic structure and flow of the adapter design pattern. We can see, there are 2 processes Process1 producing OutputA and Process2 that requires input from Process1. But in some cases, the output produced by Process1 is not of the same form as that required by Process2. Hence, An adapter is introduced between both the processes. What is the purpose of this adapter? It is nothing but a piece of code or a process that converts OutputA into a format which Process2 can use i.e OutputB.

Where can this pattern be used?

There are many cases where we can use the adapter design pattern.

  • To call function with parameter but don't have same parameters - In such cases we can convert to expected format and then call the function like integer to string
  • We have different type of class than we need : then we can use adapter to convert class type like student to person
  • Datatype of field is different than we need to process - we can convert field like string to int parsing

Real life example of adapter design pattern

There are so many examples where we use adapter patterns. One of the example we can consider of language translator.

Real time example of Adapter design pattern

As shown in image there are two people one can speak English and other speaks German. Therefore, there is no way they can communicate. Then they find another person who speaks both the language who helps them communicate.

Adapter design pattern example in software

Let's assume an example of a student who becomes an employee after candidate selection process.

We have two model objects Student.java and Employee.java. Student model is for storing the student data. Employee model stores the employee data.

public class Student {
    int rollNumber;
    String name;
    Date dob;
    .. getter and setter ...
}

public class Employee{
    int employeeId;
    String name;
    Date dateOfBirth;

    public Employee(int employeeId, String name, Date dateOfBirth) {
        this.employeeId = employeeId;
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }
    .. getter and setter ...
}

We have a EmployeeService.java class. This class creates as well as stores employee data.

public class EmployeeService{

    public void saveEmployee(Employee e){
		 .. code to create employee record
    }
}

Now let's create the code for interview selection process. The input will be student object. If interview is successful then we need to create employee record.

public class PlacementService{
    EmployeeService employeeService = new EmployeeService();
    public void process(Student student){
        // conduct interview
        // if selected in interview
        employeeService.saveEmployee(EmployeeAdaptor.getEmployee(student));
    }
}

public class EmployeeAdapter{
    public static Employee getEmployee(Student s){
        return  new Employee(s.getRollNumber(),s.name,s.getDob());
    }
}

If you have noticed, in above code we have created another class called EmployeeAdapter.java. As we have Student.java class and we can only pass employee data to saveEmployee() function. Therefore, we needed another code which can do the magic of converting student to employee.

One of the most important point to note here is that it is not necessary to name class as "Adapter". You can name class anything you want, like EmployeeUtil or StudentEmployeeMapper etc.

Benefits

  • Firstly, helps to reuse existing code
  • Secondly, incompatible code can communicate with each other
  • Additionally, alternate form of the class creation is possible
  • Also, adapter makes things work after they're designed
  • We can provide data in requested format even if we do not have

Limitations

  • The two objects must be similar or must have same features
    • For eg: Adapting a Student object to Department object is unlikely, but Adapting a Student object to Employee object is possible
  • Performance affected due to extra processes
  • All the processes communicate through adapters only

Fast track reading

  • Adapter design pattern is of structural type
  • Also known as wrappers
  • Solution for helping incompatible things to communicate with each other
  • Possible to reuse code

3 comments

Leave a Reply

Your email address will not be published. Required fields are marked *